Question

When I have an array of Sitecore IDs, for example TargetIDs from a MultilistField, how can I query the ContentSearchManager to return all the SearchResultItem objects?

I have tried the following which gives an "Only constant arguments is supported." error.

using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
    rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(x => f.TargetIDs.Contains(x.ItemId));
    rpt.DataBind();
}

I suppose I could build up the Linq query manually with multiple OR queries. Is there a way I can use Sitecore.ContentSearch.Utilities.LinqHelper to build the query for me?

Assuming I got this technique to work, is it worth using it for only, say, 10 items? I'm just starting my first Sitecore 7 project and I have it in mind that I want to use the index as much as possible.

Finally, does the Page Editor support editing fields somehow with a SearchResultItem as the source?

Update 1 I wrote this function which utilises the predicate builder as dunston suggests. I don't know yet if this is actually worth using (instead of Items).

public static List<T> GetSearchResultItemsByIDs<T>(ID[] ids, bool mustHaveUrl = true)
    where T : Sitecore.ContentSearch.SearchTypes.SearchResultItem, new()
{
    Assert.IsNotNull(ids, "ids");
    if (!ids.Any())
    {
        return new List<T>();
    }

    using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
    {
        var predicate = PredicateBuilder.True<T>();
        predicate = ids.Aggregate(predicate, (current, id) => current.Or(p => p.ItemId == id));

        var results = s.GetQueryable<T>().Where(predicate).ToDictionary(x => x.ItemId);
        var query = from id in ids
                  let item = results.ContainsKey(id) ? results[id] : null
                  where item != null && (!mustHaveUrl || item.Url != null)
                  select item;

        return query.ToList();
    }
}

It forces the results to be in the same order as supplied in the IDs array, which in my case is important. (If anybody knows a better way of doing this, would love to know).

It also, by default, ensures that the Item has a URL.

My main code then becomes:

var f = (Sitecore.Data.Fields.MultilistField) rootItem.Fields["Main navigation links"];
rpt.DataSource = ContentSearchHelper.GetSearchResultItemsByIDs<SearchResultItem>(f.TargetIDs);
rpt.DataBind();

I'm still curious how the Page Editor copes with SearchResultItem or POCOs in general (my second question), am going to continue researching that now.

Thanks for reading, Steve

Was it helpful?

Solution

You need to use the predicate builder to create multiple OR queries, or AND queries.

The code below should work.

        using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
        {
            var predicate = PredicateBuilder.True<SearchResultItem>();

            foreach (var targetId in f.Targetids)
            {
                var tempTargetId = targetId;
                predicate = predicate.Or(x => x.ItemId == tempTargetId)
            }
            rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(predicate);
            rpt.DataBind();
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top