6

I have a computed field with returnType="stringCollection", which I am using via a search result model that looks something like this:

public class MySearchResultItem : SearchResultItem
{
    // ...other properties...

    [IndexField("aliases")]
    public string[] Aliases {get; set;}
}

My search code needs to find results that have aliases beginning with a given letter (or any digit if the input is #). Here's what it looks like now:

var pattern = (letter == "#" ? "[0-9]" : letter) + ".*";
var predicate = PredicateBuilder.True<MySearchResultItem>();
// ...other clauses...
predicate = predicate.And(r => r.Aliases.Any(a => a.Matches(pattern));
var results = context.GetQueryable<MySearchResult>().Where(predicate).ToList();

Originally, I had the Aliases property as an IEnumberable<string>, but I got an error that said it must be an array. After changing it to an array, I get an exception like so:

[ArgumentException: Static method requires null instance, non-static method requires non-null instance.
Parameter name: instance]
   System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method) +5862475
   System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments) +69
   Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitLinqEnumerableAnyMethod(MethodCallExpression methodCall) +573
   Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression) +186
   ...
   System.Linq.Enumerable.ToList(IEnumerable`1 source) +70
   ... my code ...

Am I doing something wrong, or is this kind of query just not supported by the API?

If this isn't supported, is there another way to get there? Changing it from Matches to StartsWith(letter) gets rid of the error, but I would need to add 10 StartsWith clauses for the digit case and apparently StartsWith isn't "safe" to begin with.

1 Answer 1

6

When working with stringCollection fields, you can declare them in the model simply as string. When you apply any filtering logic to such a field, that logic will be treated as .Any(), meaning that the filter needs to apply to at least one string in the collection. This is in a way similar to how tokenized fields work.

Define your field in the model like this:

[IndexField("aliases")]
public string Aliases { get; set; }

And then filter like this:

predicate = predicate.And(r => r.Aliases.Matches(pattern));
1
  • 1
    Thanks, I should have thought of that. Since I also need to use the stored value of the field, I added another Property string AliasesRaw that I use for the query and keep the original string[] Aliases so I can get individual values from results.
    – Ben Golden
    Dec 6, 2016 at 14:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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