4

I'm working on a Sitecore Azure PaaS instance using the Azure Marketplace ARM template which sets up Azure Search. For much of the project things are OK, but I'm having difficulty with Multilist fields. Multilist field values are stored as text in the format of pipe delimited GUIDs. When you use the Sitecore ContentSearch API you cannot search for a particular ID within the string due to the way that Azure search works. I know that it does some weird Regex matching which throws off a bunch of stuff.

So my question is, has anyone found a way to overcome this? There doesn't seem to be a lot of help out there in reference to Azure Search with Sitecore. Googling just gets a bunch of "news" from the Fall when Update 1 came out.

var test2 = context.GetQueryable<SBJSearchItem>()
    .Where(p => p.Authors.Contains("9C66"))
    .ToArray();

var test3 = context.GetQueryable<SBJSearchItem>()
    .Where(p => p.Authors.Contains("8292632F-244A-4327-9C66-80DCF98CCAB8"))
    .ToArray();

In the code example above I have a class SBSearchItem that inherits SearchResultItem and adds the Authors property as an index field type of string (see bottom). In the code example above the test2 array returns a number of items as "9C66" matches a portion of an author's item id. But when I pass in the entire ID in the test3 array it returns 0 items.

Here's some data from my Azure Search logs showing the 2 queries. You can see how it's escaping for the URL & Regex.

?api-version=2015-02-28&search=authors:(/.*9C66.*/)&queryType=full&$count=true

?api-version=2015-02-28&search=authors:(/.*8292632F%5C-244A%5C-4327%5C-9C66%5C-80DCF98CCAB8.*/)&queryType=full&$count=true

If I use a REST client and manually pass in the following query I get all of the results as expected. It appears to be the way that the Sitecore ContentSearch API is handling the input.

?api-version=2015-02-28&search=authors:(%22%7B8292632F-244A-4327-9C66-80DCF98CCAB8%7D%22)&queryType=full&$orderby=date%20desc&$count=true

[IndexField("authors")]
public string Authors { get; set; }
  • BTW, my end goal is to be able to find all items that have been "tagged" with a certain author, even if that item has multiple authors. And this is not the Sitecore author field either. – Kevin Mar 22 '17 at 19:35
4

I discovered that if you simply use .Equals() then it will work fine. It will perform a Regex match and find all instances, including items that have multiple values in the multilist field.

var test2 = context.GetQueryable<SBJSearchItem>()
    .Where(p => p.Authors.Equals("8292632F-244A-4327-9C66-80DCF98CCAB8"))
    .ToArray();
  • That's good to know! Thanks for letting us know how you solved it. – Jarmo Jarvi Apr 6 '17 at 0:20
0

The reason the last query returns just that single result is because it's does not have the wildcard search in the beginning and end of the guid (.*), just exact match, including the {} characters. It's also encapsulated in double quotes (%22), making it an exact search match.

Now, in theory this query should return all the expected results:

?api-version=2015-02-28&search=authors:(%22%2E%2A8292632F-244A-4327-9C66-80DCF98CCAB8%2E%2A%22)&queryType=full&$orderby=date%20desc&$count=true

Can you let me know if that works?

It basically encapsulates the query in wildcard search for beginning and end. If that works, then the question is, why isn't the Contains() generating the correct query.

Things to check:

  • Add double quotes to the Cotains call, to make sure it's considered exact match. Either \" or %22
  • Add \ before the hyphens, to ensure they are not considered negative operators. Although this should not be the case, since in the log, it gets a backslash (%5C) prefixed. Also, it should be a negative operator only if there's a space in front.

https://docs.microsoft.com/en-us/rest/api/searchservice/Simple-query-syntax-in-Azure-Search?redirectedfrom=MSDN

  • I think what is happening is that the Sitecore Search API is doing a Regex.Escape against the input before sending it to Azure Search. This var authorId = "\"{8292632F-244A-4327-9C66-80DCF98CCAB8}\""; becomes this authors:(/.*%5C%22%5C%7B8292632F%5C-244A%5C-4327%5C-9C66%5C-80DCF98CCAB8%5C%7D%5C%22.*/). So it's just escaping my attempts at pre-encoding the string. – Kevin Mar 23 '17 at 11:07
0

It's worth noting the solution used by Habitat for a similar situation.

  1. It uses a computed index field to index all the templates in the inheritance hierarchy for each indexed item. The indexing code returns a List<string> of the IDs (which are formatted without dashes, brackets or braces).

  2. There is an IndexedItem class with a property called AllTemplates of type List<string> mapped with an attribute to the index field.

  3. The search code uses the Contains extension method on the AllTemplates field: expression = expression.Or(i => i.AllTemplates.Contains(IdHelper.NormalizeGuid(template)));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.