I have some content where a property is a BlockList, and every block in it has a tags property (using the Tags property editor). Specifically, I’m assigning “roles” (the tags) to a Person.
When I use the TagQuery service to get tagged content, I get the Content (i.e. documents) nodes that have been tagged - so I have no simple way of getting, say, “all the people with an Orc role”.
Is there a way to extend the TagQueries to return the specific Elements a tag was used on, or is that information actually lost as soon as the document is saved/published?
How would you do something like this (I use the Tags property editor because there are no finite list of roles).
No, the TagQuery service only looks at documents and not elements. I believe it only works if the tag property is in the document, not in an element in the Block List (although I’ve not tried it).
An alternative would be to store the tags in a field in Examine so you can query Examine rather than the TagQuery service, or store them in a custom database table at the point you save/publish. A custom table would be an optimal solution as it could contain the document and element UDI taking you directly to the required element in the Block List.
Another approach would be to reference people outside of the Block List so they are stored as content nodes in their own right, allowing them to have tags which can then be returned from the TaqQuery service.
Yeah it does actually work, even when the tag property is on a BlockList element, but the tags only reference the document, which is the problem.
The people are also separate types and are referenced in the block. I can’t put the tags on them because they’re not tied to a person but the block defines the combination of a Person and their Role
I have something that works for now, but it’s not exactly pretty .
I think an approach where I put the tag (readonly, possibly) on the Person somehow, when the document is saved would be possible, enabling me to use Examine for the querying - but that’ll become tricky when/if a role+person is removed because it doesn’t necessarily mean that that combination doesn’t exist on some other node .
Umbraco does actually pick up tags from inside block editors
But I don’t think TagQuery can return the specific block/element that matched. The tags are stored against the owning document and the outer Block List property, not against the individual block item. So TagQuery can narrow it down to “documents that contain this tag somewhere”, but not “which Person block has the Orc role”.
I’d use TagQuery to get candidate pages, then inspect the Block List manually:
var pages = tagQuery.GetContentByTag("Orc", "roles");
foreach (var page in pages)
{
var people = page.Value<BlockListModel>("people");
var matchingPeople = people?
.Where(block =>
{
var roles = block.Content.Value<IEnumerable<string>>("roles")
?? Enumerable.Empty<string>();
return roles.Contains("Orc");
});
}
If this needs to be fast or queried often, I’d look at a custom index or model the people as actual content items, because the built-in tag relationship does not preserve block-level identity.