mongodb-labs / mongo-csharp-search

C# driver extension providing support for Atlas Search
Apache License 2.0
17 stars 1 forks source link

Add expression to Search #8

Open ghendo opened 2 years ago

ghendo commented 2 years ago

Hello, If I wanted to include an Expression in the search as it is suggested not to add a match stage2, is this possible?

How would I convert the Expression<Func<T, bool>> to a SearchDefinition?

dgolub commented 2 years ago

I'm not sure where you're seeing that $search and $match should never be used together, but in many cases it's necessary to do so. The only caveat is that a $match coming after a $search won't be able to use indexes, so there could be performance concerns if the $search stage matches a very large number of documents that then need to all be processed by $match.

ghendo commented 2 years ago

You ask where this recommendation comes from. It comes from page

https://www.mongodb.com/docs/atlas/atlas-search/performance/query-performance/

Paragragph $match Aggregation Stage Usage Using a $match aggregation pipeline stage after a $search stage can drastically slow down query results. If possible, design your $search query so that all necessary filtering occurs in the $search stage to remove the need for a $match stage. The $compound Atlas Search operator is helpful for queries that require multiple filtering operations. If you must use the $match stage in your aggregation pipeline, consider using the storedSource option to store only the fields that your $match condition needs. You can then use the returnStoredSource option to retrieve stored fields.

ghendo commented 2 years ago

Regarding use of Expression<Func<T, bool>>

I found I can add in .Search .Filter(SearchBuilders.Search.Eq(predicate,true)) where predicate is Expression<Func<T, bool>>

However.. It sends the property names as is rather than the BsonElement value so will fail

So in the case of a property [BsonRequired] [BsonElement("title")] [Display(Name = "Title")] public string Title { get; set; };

Title is used for path rather than title

Is this issue fixable?

dgolub commented 2 years ago

What's the value of predicate that you're using here? The Eq function checks whether a single field is true or false, so if predicate is anything other than a single field, it's expected that that would cause an error. When I tested it myself with something like x => x.Title == "foo", it produced an appropriate error message.

I was unable to reproduce the Title vs. title issue. That could also be also related to what's being specified for predicate. Perhaps, it's hitting on some sort of edge case that isn't being handled properly.

As a general practice, it's good to provide the full code to reproduce the bug (ideally in the simplest possible way) when filing bug reports. Thanks!

ghendo commented 2 years ago

predicate is an Expression containing an arbitrary set of queries so I have misunderstood the operation. I will check with a single field. I was wanting to supply the method with two parts. One an arbitary Exprssion with whatever runtime query requested. Two an autocomplete as you type to evaluate. I will have to add the predicate in a following stage but thing thing is doing my head in to get it high performance.