Advice on Atlas Search with Match Filter

Hi

I have a large collection of data that I want to be able to run Autocomplete searches but limit to a specific group of entries. I am looking for best practices on how to set this up. Currently I have an Atlas Search Index on the fields I want to do Autocomplete Searches on and a regular Index on the filter criteria. Is this the most optimal performance configuration? I am still seeing searches running for multiple seconds, even though the filter criteria should only be searching a few hundred records. This leads me to think its searching the whole SearchIndex and then filtering after

Code Snippets below:

var compoundSearch = Builders.Search.Compound()
.Should(Builders.Search.Autocomplete(g => g.FirstName, searchString))
.Should(Builders.Search.Autocomplete(g => g.LastName, searchString))
.Should(Builders.Search.Autocomplete(g => g.Email, searchString));

var matchDescriptor = matchBuilder.In(x => x.DepartmentId, departmentIds)
& matchBuilder.Eq(x => x.IsActive, false);

GetCollection().Aggregate()
.Search(compoundSearch, indexName: “PersonName”)
.Match(matchDescriptor)
// Limit to 20 results by default
.Limit(limit)
.As()
.ToListAsync();

For anyone that comes across this, I have gotten this to be much more performant with the following changes.

First - updated Atlas Search to have all search and filter criteria. The mongo search pipeline wont take into account Match criteria

Second - Combine all search criteria, to a single Should clause and setting the MinimumShouldMatch count to 1 for all of them. Not sure if this had a performance implication, but its cleaner in code.

Third - Utilized the QueryString “OR” clause to filter on multiple match criteria.

Final Code -
var compoundSearch = Builders.Search.Compound()
.Should(Builders.Search.Autocomplete(g => g.FirstName, searchString),
Builders.Search.Autocomplete(g => g.LastName, searchString),
Builders.Search.Autocomplete(g => g.Email, searchString)
).MinimumShouldMatch(1)
.Filter(
Builders.Search.QueryString(g => g.DepartmentId, string.Join(" OR ", departmentIds)),
Builders.Search.Equals(g => g.IsActive, true)
);

return await GetCollection().Aggregate()
.Search(compoundSearch, indexName: “PersonName”)
// Limit to 20 results by default
.Limit(limit)
.ToListAsync();

Hope this helps someone else

Query improvements for the same search over half a million records, 23 seconds → 330 ms

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.