0

I can see all the records in the Solr portal when I run the query. Here is the data of one product.
https://localhost:8983/solr/stratum_products_master_index/select?q=_templatename%3A%22product%20details%20page%22

{
        "category_t_en":"Lipstick",
        "_indexname":"stratum_products_master_index",        
        "is_active_b":true,        
        "category_t":"Lipstick",        
        "title_t_en":"Claire",
        "producttags_sm":["Cosmetics"],        
        "price_t_en":"15",        
        "productimageurl_s":"/-/media/Stratum/Project/Demo/assets/img/products/product-3.jpg",      
         "_templatename":"Product Details Page",        
        "tags_sm":["8f44b11cd2fd4d10b43ed16b847b4f9b"],        
        "price_t":"15",        
        "title_t":"Claire",       
        "_name":"claire",
        "_database":"master",
        
},

But the code doesn't return any results. I doubt if the reason is the predicate, but I'm unable to figure out what.

ProductsController.cs

BaseSearchResult<ProductSearchResultItem> result = productSearcher.GetSearchResult("stratum_products_master_index", "", "", 1, 5);

ProductSearchResultItem.cs

public class ProductSearchResultItem : SearchResultItem
    {
        [IndexField("is_active")]
        public bool IsActive { get; set; }

        [IndexField("title")]
        public string Title { get; set; }

        [IndexField("category")]
        public string Category { get; set; }

        [IndexField("tags")]
        public IEnumerable<Guid> Tags { get; set; }

        [IndexField("productimageurl")]
        public string ProductImageUrl { get; set; }

        [IndexField("producttags")]
        public List<string> ProductTags { get; set; }

        [IndexField("productpricedisplay")]
        public string ProductPriceDisplay { get; set; }
    }

patch.config

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
  <sitecore role:require="Standalone or ContentDelivery or ContentManagement" search:require="solr">
    <contentSearch>
      <indexConfigurations>
        <defaultSolrIndexConfiguration>              
          <documentOptions>
            <fields hint="raw:AddComputedIndexField">
              <field fieldName="ProductImageUrl" returnType="string">Stratum.Feature.PageContent.ComputedIndexFields.ProductImageUrl, Stratum.Feature.PageContent</field>
              <field fieldName="ProductTags" returnType="stringCollection">Stratum.Feature.PageContent.ComputedIndexFields.ProductTags, Stratum.Feature.PageContent</field>
              <field fieldName="ProductPriceDisplay" returnType="string">Stratum.Feature.PageContent.ComputedIndexFields.ProductPriceDisplay, Stratum.Feature.PageContent</field>
            </fields>
          </documentOptions>
        </defaultSolrIndexConfiguration>
      </indexConfigurations>
      <configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
        <indexes hint="list:AddIndex">
          <index id="stratum_products_master_index" type="Sitecore.ContentSearch.SolrProvider.SolrSearchIndex, Sitecore.ContentSearch.SolrProvider">
            <param desc="name">$(id)</param>
            <param desc="core">stratum_products_master_index</param>
            <param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
            <configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration" />
            <strategies hint="list:AddStrategy">
              <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/manual" role:require="(ContentManagement and !Indexing) or (ContentDelivery and !Indexing)" />
              <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsyncSingleInstance" role:require="Standalone or (ContentManagement and Indexing) or (ContentDelivery and Indexing)" />
            </strategies>
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
                <Database>master</Database>
                <Root>/sitecore/content/Tenant/Stratum/Home/products</Root>
              </crawler>
            </locations>
            <enableItemLanguageFallback>false</enableItemLanguageFallback>
            <enableFieldLanguageFallback>false</enableFieldLanguageFallback>
          </index>
        </indexes>
      </configuration>
    </contentSearch>
  </sitecore>
</configuration>

ProductSearcher.cs

public class ProductSearcher
    {
        private SearchService searchService = new SearchService();

        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, pageSize);
            return query;
        }

        private Expression<Func<ProductSearchResultItem, bool>> GetSearchPredicate(string searchTerm, string tagId)
        {
            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>();
            var orPredicate = PredicateBuilder.False<ProductSearchResultItem>();

            if (!string.IsNullOrWhiteSpace(productDetailsTemplateName))
            {
                /// get only product pages
                andPredicate = andPredicate.And(x =>  x.TemplateName.Equals(productDetailsTemplateName, StringComparison.InvariantCultureIgnoreCase));

                int test = 1;

                /// get only active products
                if (test == 1)
                {
                    andPredicate = andPredicate.And(x => x.IsActive); 
                }

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

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

            /// append the naming predicate to the overall filter predicate
            var finalPredicate = andPredicate.And(orPredicate);

            return finalPredicate;
        }        
    }

SearchService.cs

public class SearchService
    {
        public IQueryable<T> GetSearchQuery<T>(string searchIndexName, Expression<Func<T, bool>> predicate) where T : SearchResultItem
        {
            IQueryable<T> query;

            using (var context = ContentSearchManager.GetIndex(searchIndexName).CreateSearchContext())
            {
                query = context.GetQueryable<T>().Filter(predicate);
            }

            return query;
        }

        public BaseSearchResult<T> GetSearchResults<T>(string searchIndexName, IQueryable<T> query) where T : SearchResultItem
        {
            int totalResults = 0;
            List<T> resultsByFilters = null;

            /// get the index
            ISearchIndex searchIndex = ContentSearchManager.GetIndex(searchIndexName);

            /// create a search context
            using (IProviderSearchContext context = searchIndex.CreateSearchContext())
            {
                /// get results from this index based on query
                SearchResults<T> searchResults = query.GetResults();

                if (searchResults != null)
                {
                    totalResults = searchResults.TotalSearchResults;
                    resultsByFilters = searchResults.Hits.Select(x => x.Document)?.ToList();
                }

                return new BaseSearchResult<T>
                {
                    TotalResults = totalResults,
                    ResultsByFilters = resultsByFilters
                };
            }
        }
    }

Update

This is the query logged in Search.log

24840 18:11:08 INFO  Solr Query - ?q=*:* AND _val_:__boost&start=3&rows=3&fl=*,score&fq=-*:*&fq=_indexname:(stratum_products_master_index)&wt=xml

enter image description here

enter image description here

7
  • 1
    Open search.log and see the query that is generated. Add it to your question. From what I can see you're creating "OR" predicate with False, like orPredicate = PredicateBuilder.False<ProductSearchResultItem>(); and then you use finalPredicate = andPredicate.And(orPredicate);so you have andPredicate AND FALSE
    – Marek Musielak
    Feb 16, 2023 at 12:36
  • @MarekMusielak I have added the solr query found in Search.log`. Could you please check.
    – sukesh
    Feb 16, 2023 at 12:43
  • q=*:* AND _val_:__boost&start=3&rows=3&fl=*,score&fq=-*:*&fq=_indexname:(stratum_products_master_index)&wt=xml that's not the query for products. This is Give me 3 results starting from 3rd result without any filters query
    – Marek Musielak
    Feb 16, 2023 at 12:44
  • But that is all there is logged in the log file :(
    – sukesh
    Feb 16, 2023 at 12:45
  • Maybe product template is not published? Debug and check the value of productDetailsTemplateName
    – Marek Musielak
    Feb 16, 2023 at 12:47

1 Answer 1

1

The problem is with your GetSearchPredicate method.

First you create orPredicate which is always false

var orPredicate = PredicateBuilder.False<ProductSearchResultItem>();

Then you use never add any Or conditions to it and instead you use it in finalPredicate:

var finalPredicate = andPredicate.And(orPredicate);

Remove that orPredicate or use it like:

var colorExpression = PredicateBuilder.False<ProductSearchResultItem>();
colorExpression = colorExpression.Or(o => o.Color == "black");
colorExpression = colorExpression.Or(o => o.Color == "white");
andExpression = andExpression.And(colorExpression);

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.