Finding all nodes with document types that inherit from particular document type
What I have is one common document type which has all the common properties I need (PARENT).. and then I have more document types that inherit from the parent document type and also have additional properties. (CHILDREN ) In the content I only create nodes from these child document types.
Is there a query that will return all nodes that have a document type that inherit from the parent document type.
Also, I need to do this without using Examine, because that has been nothing but trouble in my experience. I am using Umbraco 7.
Are you looking for a way to do this on the site? Or are you just looking for an SQL query for auditing purposes?
I think something like this will get you the data you need:
var myNodes = new List<IContent>();
var cs = Services.ContentService;
var cts = Services.ContentTypeService;
var childDocTypes = cts.GetContentTypeChildren(123);
foreach (var contentType in childDocTypes)
{
myNodes.AddRange(cs.GetContentOfContentType(contentType.Id));
}
Keep in mind that using these services is highly discouraged when you are trying to display results to front end users. These services are meant for programatically creating and updating content, document types, etc. Because these services hit the database directly, they are very slow and expensive. You can use these services to get info about doctypes and unpublished content, but it is one of the most inefficient ways to query Umbraco.
If you are using models builder this can be done without using the content service.
First you need to find all doctypes that implement your base class using this, and exclude the base class it self
var myDocTypes= PluginManager.Current.ResolveTypes<BasePage>().Where(x => x.Name != nameof(BasePage)).ToList();
Now that you have that list I prefer XPath to find all the items, because we can do it one query.
var filter = string.Empty;
foreach (var doctype in myDocTypes)
{
var alias = doctype.GetField("ModelTypeAlias");
if (alias != null)
{
filter += $"self::{alias.GetValue(null)} or ";
}
}
filter = filter.TrimEnd(" or ");
var xpath = $"id({currentContentId})[@isDoc]/ancestor-or-self::{RootNodeDocTypeAlias}//*[{filter}]";
Of course you need to replace currentContentId with id of your current page and RootNodeDocTypeAlias with the document type alias of your root item.
After that you can get all the items implementing a certain base type from the cache
var items = UmbracoContext.Current.ContentCache.GetByXPath(xpath).OfType<BasePage>();
Hi guys, thanks for all the answers and sorry for my delay.
Actually I am using Umbraco only for BE part, so I am using Umbraco API controllers. So, I guess my only choice is content service??
Michael here is an example of how my structure looks like.
Let's say in the section where I define the document types I have the following:
And in the content section I only have nodes of the inherited types (InheritedDocumentType1, InheridetDocumetType2 and InheritedDocumentType3).
So, I was looking for a way to get all the nodes that inherit from the ParentDocumentType, so I don't have to filter by EVERY document type.
If you have additional questions and it is still not clear what I want to achieve please ask.. and thanks again.
I think that I will just define a list with all the document types I need and when I iterate over the nodes I will just check if the document type of the node is in the list.
If someone thinks of a better way to do this please do tell :))
Thanks
The code I sent should work just fine in a API controller. You only need to tweak your xpath query to start from the root because you don't have a current page id.
Hi, just a thought but how about adding a unique label property (eg BasedOnDocTypeA) to each of your base docTypes and then doing a regular XPath query looking for all items that have that particular label property (as it will be inherited). To exclude any base docTypes you could check the level is greater than X - or to know if any given content item extends a given base docType then no query is required as it'll have the label property to check.
I found a way to do this by simply checking if the base document type is in the composition aliases
.Where(x => x.ContentType.CompositionAliases.ToList().IndexOf("item").
Finding all nodes with document types that inherit from particular document type
What I have is one common document type which has all the common properties I need (PARENT).. and then I have more document types that inherit from the parent document type and also have additional properties. (CHILDREN ) In the content I only create nodes from these child document types. Is there a query that will return all nodes that have a document type that inherit from the parent document type. Also, I need to do this without using Examine, because that has been nothing but trouble in my experience. I am using Umbraco 7.
Hi Kevin,
can you give us a screenshot of the content structure with some more details and the result you want?
Thanks!
/Michaël
Are you looking for a way to do this on the site? Or are you just looking for an SQL query for auditing purposes?
I think something like this will get you the data you need:
Keep in mind that using these services is highly discouraged when you are trying to display results to front end users. These services are meant for programatically creating and updating content, document types, etc. Because these services hit the database directly, they are very slow and expensive. You can use these services to get info about doctypes and unpublished content, but it is one of the most inefficient ways to query Umbraco.
Hi Kevin,
If you are using models builder this can be done without using the content service.
First you need to find all doctypes that implement your base class using this, and exclude the base class it self
Now that you have that list I prefer XPath to find all the items, because we can do it one query.
Of course you need to replace currentContentId with id of your current page and RootNodeDocTypeAlias with the document type alias of your root item.
After that you can get all the items implementing a certain base type from the cache
Dave
Hi guys, thanks for all the answers and sorry for my delay. Actually I am using Umbraco only for BE part, so I am using Umbraco API controllers. So, I guess my only choice is content service??
Michael here is an example of how my structure looks like. Let's say in the section where I define the document types I have the following:
ParentDocumentType - InheritedDocumentType1 - InheridetDocumetType2 - InheritedDocumentType3
And in the content section I only have nodes of the inherited types (InheritedDocumentType1, InheridetDocumetType2 and InheritedDocumentType3).
So, I was looking for a way to get all the nodes that inherit from the ParentDocumentType, so I don't have to filter by EVERY document type. If you have additional questions and it is still not clear what I want to achieve please ask.. and thanks again.
I think that I will just define a list with all the document types I need and when I iterate over the nodes I will just check if the document type of the node is in the list. If someone thinks of a better way to do this please do tell :)) Thanks
Hi Kevin,
The code I sent should work just fine in a API controller. You only need to tweak your xpath query to start from the root because you don't have a current page id.
Dave
Hi, just a thought but how about adding a unique label property (eg BasedOnDocTypeA) to each of your base docTypes and then doing a regular XPath query looking for all items that have that particular label property (as it will be inherited). To exclude any base docTypes you could check the level is greater than X - or to know if any given content item extends a given base docType then no query is required as it'll have the label property to check.
Thank you guys for the suggestions. I will try all of these ideas these days and I will get back to you :)
I found a way to do this by simply checking if the base document type is in the composition aliases .Where(x => x.ContentType.CompositionAliases.ToList().IndexOf("item").
Hi Kevin,
I think you are using a IContent item here ? Remember you will be hitting the database and bypassing the cache which can cause performance issues.
Dave
is working on a reply...