Skip to content

Instantly share code, notes, and snippets.

@vtml
Forked from bic742/SearchQuery.cs
Created November 22, 2021 01:49
Show Gist options
  • Save vtml/195cba6861dfaf06b808965ff1a615ab to your computer and use it in GitHub Desktop.
Save vtml/195cba6861dfaf06b808965ff1a615ab to your computer and use it in GitHub Desktop.
Extended Sitecore SearchQuery to support sorting and more complex search criteria
using GraphQL.Types;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq;
using Sitecore.ContentSearch.Linq.Utilities;
using Sitecore.ContentSearch.Utilities;
using Sitecore.Data;
using Sitecore.Data.Managers;
using Sitecore.Globalization;
using Sitecore.Services.GraphQL.Content.GraphTypes.ContentSearch;
using Sitecore.Services.GraphQL.GraphTypes.Connections;
using System.Collections.Generic;
using System.Linq;
namespace Website.SitecoreExtensions.GraphQL
{
public class ExtendedSearchQuery : Sitecore.Services.GraphQL.Content.Queries.SearchQuery
{
public ExtendedSearchQuery()
{
this.Arguments.Add(new QueryArgument<StringGraphType>()
{
Name = "sortBy",
Description = "Sort by a field"
});
this.Arguments.Add(new QueryArgument<BooleanGraphType>()
{
Name = "sortDesc",
Description = "Specify Desc vs ascending",
DefaultValue = false
});
}
protected override ContentSearchResults Resolve(ResolveFieldContext context)
{
var inputPathOrIdOrShortId = context.GetArgument<string>("rootItem");
ID rootId = null;
if (!string.IsNullOrWhiteSpace(inputPathOrIdOrShortId) && Sitecore.Services.GraphQL.Content.GraphTypes.IdHelper.TryResolveItem(this.Database, inputPathOrIdOrShortId, out var result1))
{
rootId = result1.ID;
}
if (!Language.TryParse(context.GetArgument<string>("language") ?? Sitecore.Context.Language.Name ?? LanguageManager.DefaultLanguage.Name, out var result2))
{
result2 = null;
}
var keywordArg = context.GetArgument<string>("keyword");
var nullable1 = context.GetArgument("version", new bool?());
var flag = !nullable1.HasValue || nullable1.GetValueOrDefault();
var indexName = context.GetArgument<string>("index");
var sortBy = context.GetArgument<string>("sortBy");
var dateFrom = context.GetArgument<string>("dateFrom");
var dateTo = context.GetArgument<string>("dateTo");
bool? sortDesc = context.GetArgument<bool>("sortDesc");
var fieldEquals = context.GetArgument("fieldsEqual", new object[0]).OfType<Dictionary<string, object>>();
var facets = (IEnumerable<string>)(context.GetArgument<IEnumerable<string>>("facetOn") ?? new string[0]);
SitecoreIndexableItem rootItem = null;
if (rootId != (ID)null)
{
rootItem = Sitecore.Context.Database.GetItem(rootId);
}
if (rootItem == null)
{
rootItem = Sitecore.Context.Database.GetRootItem();
}
// user can force the index by passing in an index name
// if they don't force an index, try to get determine the index from the rootitem
// if there is no root item, then just use the default Sitecore indexes and pray
var index = !string.IsNullOrWhiteSpace(indexName)
? ContentSearchManager.GetIndex(indexName)
: rootItem != null
? ContentSearchManager.GetIndex(rootItem)
: ContentSearchManager.GetIndex($"sitecore_{this.Database.Name.ToLower()}_index");
using (var searchContext = index.CreateSearchContext())
{
var queryable = searchContext.GetQueryable<ContentSearchResult>();
if (rootId != (ID)null)
queryable = queryable.Where(result => result.AncestorIDs.Contains(rootId));
if (!string.IsNullOrWhiteSpace(keywordArg))
queryable = queryable.Where(result => result.Content.Contains(keywordArg));
if (result2 != null)
{
var resultLanguage = result2.Name;
queryable = queryable.Where(result => result.Language == resultLanguage);
}
if (flag)
queryable = queryable.Where(result => result.IsLatestVersion);
foreach (var dictionary in fieldEquals)
{
var name = dictionary["name"].ToString();
var value = dictionary["value"].ToString();
if (value.Contains("notin:"))
{
var parts = value.Split(':');
var values = parts[1].Split(',');
var predicateBuilder = PredicateBuilder.True<ContentSearchResult>();
values.ForEach(
v => predicateBuilder = predicateBuilder.And(result => !result[name].Equals(v)));
queryable = queryable.Where(predicateBuilder);
}
else if (value.Contains("in:"))
{
var parts = value.Split(':');
var values = parts[1].Split(',');
var predicateBuilder = PredicateBuilder.False<ContentSearchResult>();
values.ForEach(
v => predicateBuilder = predicateBuilder.Or(result => result[name].Equals(v)));
queryable = queryable.Where(predicateBuilder);
}
else if (value.Contains("or:"))
{
var parts = value.Split(':');
var predicateBuilder = PredicateBuilder.False<ContentSearchResult>();
predicateBuilder.Or(result => result[name].Equals(parts[1]));
queryable = queryable.Where(predicateBuilder);
}
else
{
queryable = queryable.Where(result => result[name].Equals(value));
}
}
foreach (var str in facets)
{
var facet = str;
queryable = queryable.FacetOn(result => result[facet]);
}
var nullable2 = context.GetArgument("after", new int?());
if (!string.IsNullOrEmpty(sortBy))
{
if (sortDesc.HasValue && sortDesc == true)
{
queryable = queryable.OrderByDescending(result => result[sortBy]);
}
else
{
queryable = queryable.OrderBy(result => result[sortBy]);
}
}
var results = new ContentSearchResults(
queryable.ApplyEnumerableConnectionArguments<ContentSearchResult, object>(context).GetResults(),
nullable2 ?? 0);
return results;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment