Search for IContent through the ContentService on a Property
I have a requirement to update content items based on input from an external system. The way Umbraco content is linked to the external data is by sharing a unique ID, which is configured in the DataType as a Property.
What I then would like to do is to be able to search for IContent with an Id, but after digging through miles of forum posts, the only real option seems to be to use the Examine Index for quick search and then to retrieve the actual IContent through the ContentService.
In theory this sounds fine, but in practice (as many have already mentioned), the Examine index may be out of date or empty.
What I am doing now is basically getting all the content through the content service and performing a Linq query to get the right IContent object.
Needless to say, this is quite an expensive operation. Is there no other way to search for specific content through preferably the content service?
TLDR: Not possible trough contentservice, workaround below.
As far as I understand it, The Services are ways to directly interact with the database and performing crud operations. Selecting nodes(be it content,media,members) is done by ids or by ids from linked objects (children, parents, contenttypes,...).
Calculating the content (properties) of a node is pretty intensive (you have to map the name and the value in a way that can be searched) and thus is indexed with examine so that we can easily get an IpublishedContent. Which is basically an IContent or IMedia with a list of properties and some extra data.
On a side note: IPublishedContent should be named IIndexedNode or something like that, cause if you use the internal indexer instead of the standard external, you can also find unpublished nodes. And it covers both Media and Content nodes. And it's not because you can't find an IPublishedContent that it doesn't exist, it just means it can't be found in the index.
Conclusion, you cannot do this trough the Content Service.
Now, for a possible solution that doesn't use the content service (directly) nor the examine index: Use the content service to update a seperate index table.
Create a separate Table in the database
Add 2 columns, NodeId and externalID
During application startup, subscribe to the ContentService Saved event. (more info here) When the item is saved it is added to the index, get the node from the index, query the property you need and save it to the extra tabel (you can use npoco to make it easy)
When you need to update the node based on the extra id, fetch the nodeid from the extra table and get the node from the contentservice
I know it is a bit convoluted, but this way you sidestep examine (reliability) and have minimal db load (3 small ones: C/U index, fetch index, fetch node)
Thanks for this great answer! The way I've solved it now is basically by having a second Umbraco Context in a separate process indeed writing to a custom table to maintain the Property-ContentId relation. It works pretty ok, but I agree it would be better to subscribe to the Saved event as it can atomically save each entry in the custom table upon save, with the benefit that this will trigger Indexing as well - so I guess it then covers all the requirements.
Search for IContent through the ContentService on a Property
I have a requirement to update content items based on input from an external system. The way Umbraco content is linked to the external data is by sharing a unique ID, which is configured in the DataType as a Property.
What I then would like to do is to be able to search for IContent with an Id, but after digging through miles of forum posts, the only real option seems to be to use the Examine Index for quick search and then to retrieve the actual IContent through the ContentService.
In theory this sounds fine, but in practice (as many have already mentioned), the Examine index may be out of date or empty.
What I am doing now is basically getting all the content through the content service and performing a Linq query to get the right IContent object.
Needless to say, this is quite an expensive operation. Is there no other way to search for specific content through preferably the content service?
TLDR: Not possible trough contentservice, workaround below.
As far as I understand it, The Services are ways to directly interact with the database and performing crud operations. Selecting nodes(be it content,media,members) is done by ids or by ids from linked objects (children, parents, contenttypes,...).
Calculating the content (properties) of a node is pretty intensive (you have to map the name and the value in a way that can be searched) and thus is indexed with examine so that we can easily get an IpublishedContent. Which is basically an IContent or IMedia with a list of properties and some extra data.
On a side note: IPublishedContent should be named IIndexedNode or something like that, cause if you use the internal indexer instead of the standard external, you can also find unpublished nodes. And it covers both Media and Content nodes. And it's not because you can't find an IPublishedContent that it doesn't exist, it just means it can't be found in the index.
Conclusion, you cannot do this trough the Content Service.
Now, for a possible solution that doesn't use the content service (directly) nor the examine index: Use the content service to update a seperate index table.
I know it is a bit convoluted, but this way you sidestep examine (reliability) and have minimal db load (3 small ones: C/U index, fetch index, fetch node)
Thanks for this great answer! The way I've solved it now is basically by having a second Umbraco Context in a separate process indeed writing to a custom table to maintain the Property-ContentId relation. It works pretty ok, but I agree it would be better to subscribe to the Saved event as it can atomically save each entry in the custom table upon save, with the benefit that this will trigger Indexing as well - so I guess it then covers all the requirements.
is working on a reply...