Examine icon indicating copy to clipboard operation
Examine copied to clipboard

Same query but different results if executed as NativeQuery vs Fluent API

Open warrenbuckley opened this issue 2 years ago • 6 comments

Hiya @Shazwazza I have been doing some work with a project using Examine and I have been using the Fluent API to create the query I expect, but its not returning the results I would expect, especially as the lucene query it generates does return results if I use it with NativeQuery() or the Examine Search Dashboard in Umbraco.

Problem

Fluent API and NativeQuery return different results for the same Lucene search query.

Query +__NodeTypeAlias:wviewlibrary +(+wWpPropLibraryAddress:"Scotland" +wWpPropLibraryAddress:"UK")

FluentAPI NativeQuery
0 Results 3 Results

Fluent API & NativeQuery returning different results

image

Example Code (Fluent API)

public IEnumerable<IPublishedContent> FilterContent(string nodeTypeAlias, List<Guid> selectedFilters, string locationFilter)
{
    IEnumerable<string> ids = Array.Empty<string>();

    // Examine whats the query of stuff to look for as an array of strings
    // Convert the list of Guids  we have to an array of strings of the GUID IDs
    var guidStrings = selectedFilters.Select(guid => guid.ToString()).ToArray();

    if (_examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out var index))
    {
        var query = index.Searcher
            .CreateQuery(IndexTypes.Content) // Search only for Content 
            .NodeTypeAlias(nodeTypeAlias); // It must be of nodeType 'wViewCaseStudy' or whatever we pass in as parameter

        // If we have any GUID keys to filter on then add them to the query
        // Otherwise nothing selected so return all of this nodeTypeAlias
        if (guidStrings.Any())
        {
            // GroupedAnd == Try to match content where the Multi Node Tree Picker field contains the picked filter
            // Example field "wWpPropLibraryType" (Contains a CSV of UDI GUIDs)
            // But we are looking in our NEW field we added to the Examine index called "filterIds" - see ExamineContentFilterComponent.cs file
            // which is a space seperated of just the GUIDS without the umb://document/ prefix
            // The code in ExamineContentFilterComponent will always add this NEW field to examine
            // Just need to update the ExamineContentFilterComponent TODOs to ensure it finds other fielters on other document type aliases and properties
            query.And().GroupedAnd(["filterIds"], guidStrings);
        }

        // The user has also entered some form of an address/location/city etc
        // We need to filter the results by this location
        if(string.IsNullOrEmpty(locationFilter) == false)
        {
            // On the Library doctype we know the address is stored in the field "wWpPropLibraryAddress"
            if(nodeTypeAlias == WViewLibrary.ModelTypeAlias)
            {
                // Spliting by comma because the location filter could contain a city and the country
                // For example "Scotland, UK" - so we need to match both
                // With us just searching on the Field() it would match if it found either the city or the country
                // Which would give confusing results
                var locationParts = locationFilter.Split(',');
                var locationPartsExamineValues = new List<IExamineValue>();
                foreach (var part in locationParts)
                {
                    // Calling .Escape() on a string does ExamineValue(Examineness.Escaped, s)
                    locationPartsExamineValues.Add(new ExamineValue(Examineness.Escaped, part.Trim()));
                }
                
                // Commented out this approach as the string parts are not being escaped with quotes
                //query.And().GroupedAnd(["wWpPropLibraryAddress"], locationParts);
                query.And().GroupedAnd(["wWpPropLibraryAddress"], query: locationPartsExamineValues.ToArray());
            }
        }

        // Execute the Examine query and select just the IDs
        // Produces the query
        // +__NodeTypeAlias:wviewlibrary +(+wWpPropLibraryAddress:"Scotland" +wWpPropLibraryAddress:"UK")
        // Which in Examine dashboard works with the results, where via this it doesn't                
        var queryNative = index.Searcher.CreateQuery().NativeQuery("+__NodeTypeAlias:wviewlibrary +(+wWpPropLibraryAddress:\"Scotland\" +wWpPropLibraryAddress:\"UK\")");
        var queryNativeResults = queryNative.Execute();
        var queryNativeResultsCount = queryNativeResults.TotalItemCount;

        var results = query.Execute();
        var totalResultCount = results.TotalItemCount; 
        ids = results.Select(x => x.Id);
    }

    // For all the IDs returned by the Examine query, return the IPublishedContent from the content cache
    foreach (var id in ids)
    {
        yield return _umbracoHelper.Content(id);
    }
}

warrenbuckley avatar Feb 15 '24 14:02 warrenbuckley

Well what is the exact string output of the fluent query when you do a ToString() on the query?

Also, could you simplify this to make it as simple as possible to reproduce?

Shazwazza avatar Feb 15 '24 16:02 Shazwazza

The fluent query when doing a .ToString() on it returns this "{ Category: content, LuceneQuery: +__NodeTypeAlias:wviewlibrary +(+wWpPropLibraryAddress:\"Scotland\" +wWpPropLibraryAddress:\"UK\") }"

I will update the example and remove my noisy comments and stuff so you have something to work with...

warrenbuckley avatar Feb 15 '24 16:02 warrenbuckley

As I just suck at explaining myself clearly, perhaps this video may help highlight the issue

https://github.com/Shazwazza/Examine/assets/1389894/48cbcb78-82c5-4567-85f6-6f669d5b46df

warrenbuckley avatar Feb 15 '24 16:02 warrenbuckley

Hi @Shazwazza I have written a test to show this issue. Would you want it as a PR submitted to show the issue or just the code pasted here in this issue?

warrenbuckley avatar Feb 21 '24 13:02 warrenbuckley

Yeah, if you have written a FluentApiTest as part of Examine codebase, a PR would be the easiest place for me to start.

Shazwazza avatar Feb 21 '24 15:02 Shazwazza

One PR which I think highlights the issue https://github.com/Shazwazza/Examine/pull/377

warrenbuckley avatar Feb 21 '24 20:02 warrenbuckley

See comment https://github.com/Shazwazza/Examine/pull/377#issuecomment-2037901901

Shazwazza avatar Apr 04 '24 18:04 Shazwazza