ContentManager.GetMany(), but queryable

Topics: Core, Writing modules
Developer
May 3, 2012 at 6:53 PM
Edited May 5, 2012 at 11:31 AM

I first came to this problem previously but the issue "Optimize search results page to use IContentManager.GetMany()" seems to be impossible to solve (efficiently) without some sort of GetMany query.

The problem

Currently if we only know the ids of a set of content items but nothing about their structure (e.g. we don't know what parts they have attached) there is only one possibility to list them, using ContentManager.GetMany(). However GetMany() returns the collection of all matching items, therefore further querying (filtering, ordering, counting) is only possible on that collection of all items.

Using ContentManager.Query() it's not possible because to filter for a set of ids we should use the Where() method, but that requires a ContentPartRecord as a type parameter. This can't be used without the assumption that the items have some common part, having a record attached (CommonPart is a quite good guess, but not perfect).

This means, AFAIK, that if I want to e.g. count the items having ids contained in a collection I have to fetch all the matching items and then count them with LINQ to objects. This could be better.

The solution?

Since all content items have a ContentItemRecord, as far as I can guess, it should be theoretically possible to have a IContentQuery GetManyQuery(IEnumerable<int> ids). If this is possible, it would be great!

 

What do you think?

Developer
May 7, 2012 at 9:14 AM

I've opened an issue for further evaluation.

Developer
May 31, 2012 at 11:58 AM

I've updated the issue with examples that make sense.

Developer
Jul 23, 2012 at 10:58 AM
Edited Jul 23, 2012 at 8:26 PM

I've implemented a Where() methods that takes a collection of ids for ContentQuery in this fork.

Example usage:

 

var items = _contentManager.Query().Where<CommonPartRecord>(r => r.OwnerId == 2).WhereIdIn(new int[] { 15, 16, 17 }).List();
items = _contentManager.Query("Page").WhereIdIn(new int[] { 15, 16, 17 }).List();
items = _contentManager.Query().WhereIdIn(15, 16, 17).List();
var itemCount = _contentManager.Query().WhereIdIn(new int[] { 15, 16, 17 }).ForVersion(VersionOptions.Published).Count();

 

What this enables:

  • Filtering on ids alone (this is possible also with GetMany(), but...)
  • Filtering on ids in a query without having to make assumptions on record types used by the content items (this is useful if you build the base query with id filtering, then further narrow the same query somewhere else; while the second code can make assumptions about the parts used, the first can't)
  • Counting items with specific ids and other criteria (this is not the same as counting the ids)
Coordinator
Jul 23, 2012 at 6:31 PM

mmh. I would at least rename that to something like 'WhereIdIn'. Just 'Where' doesn't make much sense and isn't very expressive of the purpose of the API.

Coordinator
Jul 23, 2012 at 6:32 PM

Also, make an overload that takes a params int[], so your above examples could also be written .WhereIdIn(15, 16, 17)

Developer
Jul 23, 2012 at 8:26 PM
Edited Jul 23, 2012 at 8:27 PM

Good ideas, thanks! I wasn't satisfied with naming it "Where" either. I've made these changes (updated the examples accordingly).