Guy MacArthur Team : Web Development Tags : Web Development Search Umbraco

Getting Descendants in Umbraco Examine

Guy MacArthur Team : Web Development Tags : Web Development Search Umbraco

I ran into an issue the other day where I wanted to retrieve the descendants of a content page as part of a filtered search. In a scenario like this I might have opted for using the IPublishedContent.Descendants() method however I decided to try using a Lucene query for two reasons:

  1. I’ve stored more data for many of the index entries to optimize search performance and I want to search across it as well
  2. And why not? It’s always fun to try something new

Okay, so here’s how I achieved this.

Each content node has a path value to it. This is a comma separated ordered list of content node IDs of the ancestors of the node and it’s own ID value. For example, it might look something like this:

-1,1061,1114

where -1 is the root content node, 1061 is the homepage and 1114 is the current content node’s ID. This also represents its place in the content tree and is always unique for each node. So, in its own right, it’s an identifier as well.

Descendants of this content node will have paths with more IDs added on to this. A child may look like this:

-1,1061,1114,1119

and a child of that node may look like this:

-1, 1061, 1114, 1119, 1124

and so on.

So, in order to get all descendants of a node I use the ISearchCriteria.RawQuery() method to execute a wildcard query on the path. Example:

mySearchCriteria.RawQuery(@“+path:\-1,1061,1114,*”)

Two things to note here. First, escaping the -1 with the backslash character (@ to make it a string literal else the backslash would need it’s own backslash to escape itself). Needs to be done as lucene will explode on impact trying to parse the term starting with a dash (negative sign). Second, the trailing comma and kleene star. The star is for wildcard matches, so the query will match anything trailing the path value. The comma will match only descendant paths of the node path supplied. That’s because any descendants will have that separating comma in their path. If you were to leave that trailing comma out, your search results set would be descendants as well as the specified node. That would be equivalent to IPublishedContent.DescendantsOrSelf(), which actually may be useful in some cases as well.

As I mentioned earlier, you can also achieve this using the IPublishedContent.Descendants() method on the content node, however, I can expand on the search query to include other fields to search against. This also includes custom fields I’ve added during the GatheringNodeData event.

mySearchCriteria.RawQuery(@“+path:\-1,1061,1114,* +articleYear:2015 +nodeTypeAlias:BlogArticle”)

articleYear could be a value I extract from the createDate value of a content node as it’s being indexed, and I may use it as part of a filter set in the view. This is a simple example, however, you can see where you can get pretty clever with your queries if you want or needed to.

Okay, well, good luck out there and happy coding.