Predicate Builder

224 views
Skip to first unread message

Ettienne

unread,
Nov 4, 2010, 6:11:57 AM11/4/10
to mongodb-csharp
I am looking at doing a method that can take advanced queries to
render results with and or and exclude query operators.

So a query like: "the quick brown fox" would render results that
include any of the words

A query like: "the -quick brown fox" would render results with any of
the included words but excludes the word quick

A query like "the +quick +brown +fox" would render results that
include all the words prefixed with a + and "the" being optional.

The closest thing I could find as a LINQ example was.

http://www.albahari.com/nutshell/predicatebuilder.aspx

Which describes a similiar scenario

public List<clientDoc> GetDocumentList(bool published, int page, int
pageSize,List<String> searchTerm)
{
//PredicateBuilder
var predicate = PredicateBuilder.False<clientDoc>();
var allDocs = (from p in GetDocumentsTable().Linq()
where p.published == published select p);
foreach(string searchWord in searchTerm)
{
predicate = predicate.Or(p =>
p.LoweredContent.Contains(searchWord.ToLower()));
}
return allDocs.Where(predicate).Skip((page - 1) *
pageSize).Take(pageSize).ToList();
}

I tried the predicate builder class but keep getting one result with
null fields.

Any guidance or suggestions would be appreciated


craiggwilson

unread,
Nov 4, 2010, 12:21:42 PM11/4/10
to mongodb-csharp
This is technically a supported area, but we can't cover all
scenarios. So, if you could create a small little console program
that demonstrates the issue (or better yet, write a unit test we can
just plug into our system), we'll try and work it out.

Ettienne

unread,
Nov 6, 2010, 10:11:07 PM11/6/10
to mongodb-csharp
Hi Craig, thanks for the reply.
I managed to do a small console application to demonstrate the theory.
Please download it here and let me know what your thoughts are

http://alphadoc.webhop.net/MongoCsharpPredicateBuilder.zip

The example I did takes search terms like

"The +quick" or "+quick -fox"

Ettienne

unread,
Nov 8, 2010, 5:39:49 AM11/8/10
to mongodb-csharp
I managed to work out the problem.
Reading the below article properly details that if you are using the
predicate builder with an entity framework a few tweaks are required.

http://www.albahari.com/nutshell/linqkit.aspx

1. Call AsExpandable() on the Table<> object
2. Call Compile() on the expression variable, when used on an
EntitySet or EntityCollection.

The AsExpandable and Predicate Builder are all included in an assembly
here:
http://www.albahari.com/nutshell/LinqKit.zip

For anyone who might be interrested the working method looks something
like this:

public List<Document> GetDocumentList(bool published, int
page, int pageSize,List<String> searchTerm)
{
searchTerm = searchTerm.Select(a => a.Replace("\"", "
")).ToList();
var predicate = PredicateBuilder.True<Document>();
var allDocs = (from p in
GetDocumentsTable().Linq().AsExpandable()
where p.published == published select p);
foreach(string searchWord in searchTerm)
{
switch (searchWord.Substring(0, 1))
{
case "+":
predicate = predicate.And(p =>
p.LoweredContent.Contains(searchWord.Substring(1).ToLower()));
break;
case "-":
predicate = predicate.And(p => !
p.LoweredContent.Contains(searchWord.Substring(1).ToLower()));
break;
case " ":
predicate = predicate.And(p =>
p.LoweredContent.Contains(searchWord.Substring(1).ToLower()));
break;
default:
predicate = predicate.Or(p =>
p.LoweredContent.Contains(searchWord.ToLower()));
break;
}
}
return allDocs.Where(predicate.Compile()).Skip((page - 1)
* pageSize).Take(pageSize).ToList();
Reply all
Reply to author
Forward
0 new messages