Part 2 – The Generic Workaround
The obvious solution is to make a loose query that returns a superset of what you’re looking for, similar to the query in my first sample:
/odata.svc/CustomMetas?$filter=KeyName eq 'color' and StringValue eq 'blue'&$expand=Component/ComponentPresentations
Then on the application side filter out the results the old fashioned way (loop: foreach “blue†component check if it is also round, else skip). It’s still unwanted bytes over the wire.
This is actually OK most of the time because in the majority of scenarios you might only have a few Component Presentations published even with the loose set of Custom Metas. And if you have 100,000 DCPs in your broker, then it’s probably time to unpublish some stale content.
Side Note: Keep the content in the Broker DB up-to-date for optimal performance. Unpublish any content that is stale and no longer shown to the visitors.
In some cases the lesser evil might be to choose ComponentPresentations as the entry point with the $filter set on the Template, and finish refining your set in your app. For example:
/odata.svc/ComponentPresentations?$filter=TemplateId eq ‘83'&$expand=Component/CustomMetas
(note: 83 is just a CT ID in my system)
then loop: for each ComponentPresentation if it contains CustomMeta color=blue and CustomMeta shape=round.
You will need to perform an analysis on your use case. Will you have more Components of a given Schema tagged with CustomMetas vs. ComponentPresentations of a given Template? The goal here is to choose the approach yielding the smaller resultset to be sent across HTTP.
Nice approach, Nick! I personally would have just executed multiple queries and then intersected the results in app-logic. But that would be lots more bytes over the wire.
As you know, I recently experimented with OData Query Extension (http://yatb.mitza.net/2013/06/url-syntax-for-odata-query-extension.html) and your query could be re-written as:
/odata.svc/QueryComponentPresentations(SchemaTitle=Article)?$filter=ComponentMetaValue(ComponentMetaKey(‘color’), ‘red’) and ComponentMetaValue(ComponentMetaKey(‘shape’), ’round’)
… which would be parsed into a Criteria object and performed by CD API on the OData server.
Thanks for the comment Mihai. I really like your approach. I do hope that future releases of the CD Web Service will have this capability built-in.
As a side note, I recall having a conversation with someone from R&D, and he mentioned that OData on the back side does not wrap the standard CD API as I had assumed. It uses a totally redesigned set of DB queries which are much more performant than those of the classic CD API.
Hi Nickoli,
Is this issue solved in Web 8 or 8.5 with Content Service microservice?
That’s a great question. The new version of Tridion supports GraphQL, which is supposed to be a lot more flexible for querying. I’ve not done a POC on this specifically yet. Please share your findings with us if you get there first.
There are some examples of ‘or’ joins around the 47 minute mark in the following SDL BrightTALK about Tridion Sites 9 and the new Public Content API:
https://www.brighttalk.com/webcast/15345/327155?utm_source=SDL&utm_medium=brighttalk&utm_campaign=327155