0

I have an item which has 2 language versions - English & Chinese. This Search query is returning both versions when the expected is only English.

Not passing the languageCode so by default it is en.
Is it the logic on how I'm building the predicate.

public BaseSearchResult<ProductSearchResultItem> GetSearchResult(string searchIndexName, string searchTerm, string tagId, int pageNumber, int pageSize)
        {
            var query = GetSearchQuery(searchTerm, tagId, pageNumber, pageSize);
            BaseSearchResult<ProductSearchResultItem> result = searchService.GetSearchResults<ProductSearchResultItem>(searchIndexName, query);
            return result;
        }

        private IQueryable<ProductSearchResultItem> GetSearchQuery(string searchTerm, string tagId, int pageNumber, int pageSize)
        {
            var predicate = GetSearchPredicate(searchTerm, tagId);
            IQueryable<ProductSearchResultItem> query = searchService.GetSearchQuery<ProductSearchResultItem>(Constants.SearchIndexes.Products, predicate);

            /// Apply pagination 
            query = query.Page((pageNumber - 1), pageSize);
            
            return query;
        }

private Expression<Func<ProductSearchResultItem, bool>> GetSearchPredicate(string searchTerm, string tagId, string languageRegionalIsoCode = "en")
        {
            Item productDetailsTemplateItem = SitecoreUtility.GetItem(Templates.ProductDetailsPage.ID);
            string productDetailsTemplateName = productDetailsTemplateItem != null ? productDetailsTemplateItem.Name : string.Empty;

            /// Initialize queries with True for AND queries and False for OR queries
            var andPredicate = PredicateBuilder.True<ProductSearchResultItem>();

            if (!string.IsNullOrWhiteSpace(productDetailsTemplateName))
            {
                /// get only product pages of the specified language
                andPredicate = andPredicate.And(x => x.TemplateName.Equals(productDetailsTemplateName, StringComparison.InvariantCultureIgnoreCase));
                    
                ///get items of specified language
                andPredicate = andPredicate.And(x => x.Language.Equals(languageRegionalIsoCode, StringComparison.InvariantCultureIgnoreCase));

                /// get only active items
                andPredicate = andPredicate.And(x => x.IsActive);

                ///filter by searchTerm
                if (!string.IsNullOrWhiteSpace(searchTerm))
                {
                    andPredicate = andPredicate.And(x => x.Title.Like(searchTerm, 0.75f));

                    foreach (var t in searchTerm.Split(' '))
                    {
                        var tempTerm = t;
                        andPredicate = andPredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*").Boost(5.5f));
                        andPredicate = andPredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*"));
                        andPredicate = andPredicate.Or(p => p.Title.Equals(tempTerm));
                    }
                }

                ///filter by tag
                if (!string.IsNullOrWhiteSpace(tagId))
                {
                    Guid tagGuid = new Guid(tagId);
                    andPredicate = andPredicate.And(x => x.Tags.Contains(tagGuid));
                }
            }            

            return andPredicate;
        }  

This is the query in Search.log

INFO Solr Query - ?q=(((((_templatename:("Product Details Page") AND _language:("en")) AND is_active_b:("True")) AND title_t:(claire~0.75)) OR (title_t:(claire*))^5.5 OR title_t:(claire*) OR title_t:("claire")) AND tags_sm:("8f44b11cd2fd4d10b43ed16b847b4f9b")) AND val:__boost&start=0&rows=3&fl=*,score&fq=_indexname:(stratum_products_master_index)&wt=xml

claire is the "Title" of the item.

2
  • 1
    What is the query sent to Solr?
    – Marek Musielak
    Commented Feb 22, 2023 at 8:52
  • @MarekMusielak I have updated my question with the log entry now. Please check.
    – sukesh
    Commented Feb 22, 2023 at 8:56

1 Answer 1

1

You have an issue while adding search term predicate to your query.

You just have your main query and you add OR Title Like SearchTerm OR ... so it's enough that title contains search term and none of the other conditions is needed to evaluate to true:

if (!string.IsNullOrWhiteSpace(searchTerm))
{
    andPredicate = andPredicate.And(x => x.Title.Like(searchTerm, 0.75f));

    foreach (var t in searchTerm.Split(' '))
    {
        var tempTerm = t;
        andPredicate = andPredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*").Boost(5.5f));
        andPredicate = andPredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*"));
        andPredicate = andPredicate.Or(p => p.Title.Equals(tempTerm));
    }
}

Instead it should be:

if (!string.IsNullOrWhiteSpace(searchTerm))
{
    var titlePredicate = PredicateBuilder.False<ProductSearchResultItem>();
    titlePredicate = titlePredicate.Or(x => x.Title.Like(searchTerm, 0.75f));

    foreach (var t in searchTerm.Split(' '))
    {
        var tempTerm = t;
        titlePredicate = titlePredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*").Boost(5.5f));
        titlePredicate = titlePredicate.Or(p => p.Title.MatchWildcard(tempTerm + "*"));
        titlePredicate = titlePredicate.Or(p => p.Title.Equals(tempTerm));
    }

    andPredicate = andPredicate.And(titlePredicate);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.