How use QueryOver on NHibernate to select custom result - nhibernate

I have this code to return all colors with have some text:
public IEnumerable<Color> FindStartingWith(string term)
{
return Session.QueryOver<Color>().Where(color => color.Name.IsLike(text, MatchMode.Anywhere)).List();
}
But what I want to do, is return a STRING IEnumerable containing only a list of color.Name...
How can I do that with QueryOver?
Thanks
Junio

Syntax may not be exactly right but should be somethign like:
public IEnumerable<string> FindStartingWith(string term)
{
return Session.QueryOver<Color>()
.Select(color => color.Name)
.Where(color => color.Name.IsLike(text, MatchMode.Anywhere))
.List<string>();
}

Related

Ravendb Search with OrderBy not working

Im using the latest build of RavenDB (3.0.3800)
When I run a simple query with a Search and Orderby the Search is ignored. If I remove the OrderBy the Search works and returns the correct results
var query = _session.Query<Index_All.ReduceResult, Index_All>()
.Customize(x => x.WaitForNonStaleResults())
.Search(x => x.SearchTerm, "Some String")
.OrderBy(x => x.PublishDate);
This just returns all results, ignoring my Search completely.
Here is my Index:
public class Index_All : AbstractIndexCreationTask<MyDocuemnt,Index_All.ReduceResult>
{
// query model
public class ReduceResult
{
public string SearchTerm { get; set; }
public DateTimeOffset PublishDate { get; set; }
}
public Index_All()
{
Map = documents => from d in documents
let customer = LoadDocument<Customer>(d.Customer.Id)
let owner = LoadDocument<Customer>(d.Owner.Id)
select new
{
SearchQuery = new object[]
{
customer.Name,
owner.Name,
},
d.PublishDate,
};
Index(x => x.SearchTerm, FieldIndexing.Analyzed);
}
}
I have no idea why this is happening, the only work around i have is to return the result unordered. Can anyone spot what the problem is here ?
Thanks
You probably don't want the orderby to work. The result of a [full text] Search is going to be ordered by Lucene score. That's going to give you the best matches for the search terms provided by the user. Given that, ordering by publish date would "ruin" the quality of the results.
However, I just tried this with v30k, and it appears to use the order by properly after filtering using Search.
Edit - I notice you're using "SearchTerm" for the query model and the analyze expression, but you're indexing "SearchQuery". Make those the same and it should work.

How can I select the root entity and child entity count using QueryOver in NHibernate?

I have a pretty simple query I'm trying to convert to NHibernate's QueryOver syntax, but I'm having difficulty. The original SQL query is functionally the same as:
SELECT [Post].*, (
SELECT Count(*)
FROM [Comment]
WHERE [Comment].[PostId] = [Post].[Id]) AS [CommentCount]
FROM [Post]
The problem is I'm having difficulty converting this to QueryOver syntax. I tried defining a summary class containing both the Post and the CommandCount as such:
public class PostSummary
{
public Post Post { get; set; }
public CommentCount { get; set; }
}
And then defining the query with a couple of selects:
Post lPostAlias = null;
Comment lCommentAlias = null;
var lCommentSubquery = QueryOver.Of(() => lCommentAlias)
.Where(() => lCommentAlias.Post.Id == lPostAlias.Id)
.ToRowCountQuery();
PostSummary lPostSummaryAlias = null;
session.QueryOver(() => lPostAlias)
.SelectList(list => list
.Select(x => x).WithAlias(() => lSummary.Post)
.SelectSubQuery(lCommentSubQuery).WithAlias(() => lSummary.CommentCount)
.List<PostSummary>();
An exception gets thrown with the error message:
could not resolve property: of: Project.Models.Post
So it looks like it doesn't like the .Select(x => x) part of the query. I was hoping to find something along the lines of 'Projections.RootEntity()` but alas there is no such thing that I can find.
Can someone explain what I'm doing wrong and guide me to the proper way to do this basic query? I imaging I could select all the properties of Post that I want, but worry that I'll lose the ability to take advantage of the proxy sub-classes NHibernate generates for lazy-loading purposes and is not what I want.
using the LINQ provider you can write
var query = from post in session.Query<Post>()
select new PostSummary { Post = post, CommentCount = post.Comments.Count };
return query.ToList();

RavenDB String.Contains on multi map index

So far I have an index like this:
public class Animals_Search : AbstractMultiMapIndexCreationTask<Animals_Search.Result> {
public class Result {
public object[] Content { get; set; }
}
public Animals_Search() {
AddMap<Dog>(a => from b in a select new Result { Content = new object[] { b.Name, b.Breed} });
AddMap<Cat>(a=> from bin docs select new Result { Content = new object[] { b.Name, b.Breed} });
Index(x => x.Content, FieldIndexing.Analyzed);
}
}
And a query like this:
session.Query<Animals_Search.Result, Animals_Search>()
.Search(a => a.Content, match)
.As<Animal>()
.ToList();
This works if I provide search terms like "Collie" or "Terrier", but not "Coll" or "Terr"
How do I rewrite the query to work something like String.Contains("Terr")?
RavenDB make it hard to do contains query, because for the most part, they aren't needed.
What you probably want is to do a StartsWith, instead.
session.Query<Animals_Search.Result, Animals_Search>()
.Where(a => a.Content.StartsWith(match))
.As<Animal>()
.ToList();

RavenDB Index is not working when using SelectMany in Map Function

Based on this article from Ayende i have created the following index definition
public class ProductsSearch : AbstractIndexCreationTask<Product, ProductsSearch.Result>
{
public class Result
{
public string Query { get; set; }
}
public ProductsSearch()
{
Map = products => from product in products
select new
{
Query = new object[]
{
product.Title,
product.Tags.Select(tag => tag.Name),
product.Tags.SelectMany(tag => tag.Aliases, (tag, alias) => alias.Name)
}
};
Index(x => x.Query, FieldIndexing.Analyzed);
}
}
One difference is that i must use a SelectMany statement to get the aliases of a tag.
A tag can have many aliases (i. e. tag: mouse alias:pointing device)
I have no idea why the SelectMany line breaks the index. If i remove it, the index works.
This should work:
Map = products => from product in products
from tag in product.Tags
from alias in tag.Aliases
select new
{
Query = new object[]
{
product.Title,
tag.Name,
alias.Name
}
};

RavenDB: How to query with multiple search terms

My entity is:
class Resource
{
string Name;
string EmployeeId;
}
How do I query for resources of multiple employees? I tried this:
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => employeeIds.Contains(r.EmployeeId))
.ToArray();
}
However that gives me NotSupportedException: Method not supported: Contains. Then I tried the following method:
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => employeeIds.Any(v => v == r.EmployeeId))
.ToArray();
}
That throws NotSupportedException: Expression type not supported: System.Linq.Expressions.TypedParameterException.
In SQL it would be something like:
SELECT * FROM resource WHERE employeeid IN (1, 2, 3)
My question is, how do I perform this query in RavenDB?
You can use the In operator. If I remember correctly your code should look like this:
using Raven.Client.Linq;
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => r.EmployeeId.In<string>(employeeIds)))
.ToArray();
}