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?

1 Answer 1

3

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));
7
  • 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
    Commented Mar 12, 2019 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. Commented Mar 12, 2019 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
    Commented Mar 12, 2019 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. Commented Mar 12, 2019 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)); Commented Mar 13, 2019 at 0:27

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.