3

I'm currently converting Sitecore queries to use Contentsearch. There is a query that uses ancestor-or-self.

Specifically it's looking for an item with a template. Sample code below:

  Sitecore.Context.Database.SelectSingleItem("/sitecore/content/Site/Home/ancestor-or-self::*[@@templateid='{SAMPLE-TEMPLATE-ID}']");

The way I'm doing Content search is below:

//Prepare Search
var query = PredicateBuilder.True<SearchResultItem>();
ID TemplateId = new ID(this.Templateid); // Assume this is the SAMPLE-TEMPLATE-ID
query = query.And(x => x.TemplateId.Equals(TemplateId));
SitecoreIndexableItem indexable = new SitecoreIndexableItem(Sitecore.Context.Database.GetRootItem());

//Get Item
var searchIndex = ContentSearchManager.GetIndex(indexable);
using (var context = searchIndex.CreateSearchContext())
{
    var queryable = context.GetQueryable<SearchResultItem>().Where(query);
    var myItem = Sitecore.Context.Database.GetItem(queryable.ToList().First().ItemId);
}

With that code, I'm able to get the item with the template ID. However it is not within the path of /sitecore/content/Site/Home only. How can I query the result that would get a similar result to the ancestor-or-self query?

2

I would recommend creating a list of the IDs of the ancestors and using that to filter your results:

Item item = GetItemFromWhichToFindAncestors();

// item.Paths.LongID is a path to this item, except it uses IDs instead of item names
IEnumerable<ID> ids = item.Paths.LongID.Split(new [] {"/"}, StringSplitOptions.RemoveEmptyEntries).Select(id => new ID(id));

query = query.And(x => ids.Contains(x.ItemId));
  • With your solution, I would still need to get the item of each ID and check their templateId if it matches. I would need to loop it which kind of defeats the purpose of using contentsearch? – qwert Mar 12 '19 at 13:57
  • No, you don't need to do that. That's the point of using the query.And() method. The And makes sure that both conditions are met before returning any items. – Dan Sinclair Mar 12 '19 at 14:38
  • I don't understand. From your example, the "item" variable would be "Home" from "/sitecore/content/Site/Home" example since that is what's given then I'd get each ID of sitecore, content, site, and home and put it in the variable "ids". Wouldn't your next query return "Home"? – qwert Mar 12 '19 at 14:58
  • 1
    You would need to add my code into your existing code so that both conditions are added to the query. You will need the template condition and the path condition in order for them to work together. Then it will work just like the Sitecore query you've referenced in your question. – Dan Sinclair Mar 12 '19 at 15:22
  • It might be easier to compare using the item path, since the ancestor's path will be a substring of the main item's path. query = query.And(x => item.Paths.Path.Contains(x.Paths.Path)); – Fredric Foo Mar 13 '19 at 0:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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