I was creating a custom segmentation rule predicate for Sitecore 9, and when I tried to create a segment using the rule, I got an error inside Sitecore’s List Manager:
Field could not be found in the model or the field is not enabled for indexing/searching
That’s kind of annoying. What caused this? Well, it was a long, painful odyssey finding out.
TL;DR – If you’re using an extension method to get a facet for your CreateContactSearchQuery method – like Sitecore do – it’s method name must match the Facet Key name.
No, I’m not kidding.
I spent ages reviewing all the steps of
- creating a custom facet (Mine is “CustomTagsFacet“. That’s both the class name, and the Facet Key name)
- deploying it
- generating and deploying .JSON files
- deploying Merge Handlers
- and deploying .xml configuration files
…to both Sitecore and to XConnect. All seemed right; I couldn’t find an issue.
Obviously, the error message seems to be about validating the structure of the XdbModel for querying against. I found that this was being thrown in the the Sitecore.XConnect.Search.QueryNodeModelValidator.ThrowUnknownFieldException() method:
Well, that’s interesting, and the code around is validating the model to query against – but it’s kind of hard to see what the model actually contains, and what the error is. It’s pretty complex to reverse engineer.
Eventually one of my colleagues pointed out that the path mentioned in the error seemed a bit odd. I didn’t think I had any entities in the solution called ‘CustomTags‘. I have classes CustomTagsFacet and CustomTag (without the ‘s’). No CustomTags – or so I thought. Searching, though, turned up an innocuous looking extension class:
That looks fine, doesn’t it? It’s just a helper to get me the CustomTagsFacet from a Contact. It is used in the CreateContactSearchQuery method for my segmentation rule. This method is required by the IContactSearchQueryFactory interface.
… and I’ll be honest, I used ILSpy to crib a lot of this from the Sitecore.XConnect.Segmentation.Predicates.Contacts namespace:
These examples mostly seem to use helper extension methods to retrieve facets:
… so I’d copied the same. This is where things came unstuck. My query was using the ‘CustomTags‘ name as the key to the field in my XdbModel – and hence the error.
My colleague suggested changing the name of my extension method. We did, and the error message changed. We realised then that the extension method name must match the Facet Key name. Yeah, really. Look at some example from Sitecore’s own code:
The method name always matches the Facet Key name (though not necessarily the facet’s classname).
So my error was in the extension method name. It didn’t match the contact DefaultFacetKey (“CustomTagsFacet”):
Kind of hard to believe. I changed the method name:
… to match my facet key name (the constant DefaultFacetKey above).
Once I’d done this, the error went away and my segmentation rule started returning correct results.
Only took 2 days to work that out…
Links:
- https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/facets/creating-facets/index.html
- https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/extend-model/index.html
- https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/managing-model/deployment.html
- https://doc.sitecore.net/developers/xp/segmentation/create-a-custom-predicate.html
- https://doc.sitecore.net/developers/xp/xconnect/xconnect-client-api/contacts/merge-contacts.html
- https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/facets/facet-merge-handler.html