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
search.log
and see the query that is generated. Add it to your question. From what I can see you're creating "OR" predicate withFalse
, likeorPredicate = PredicateBuilder.False<ProductSearchResultItem>();
and then you usefinalPredicate = andPredicate.And(orPredicate);
so you haveandPredicate AND FALSE
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 isGive me 3 results starting from 3rd result without any filters
queryproductDetailsTemplateName