1
public class Objekt
{
    public Foo[] FooList{ get; set; }
}

public class Foo
{
    public string Value{ get; set; }
}

In my query RavenDb, I want to match each Objekt having an entry in FooList which have its string property "Item" starting by any string in a table of string.

tableStrings is a string[].

var query = session.Query<Objekt>();
query = query.Where(x=> tableStrings.Any(y => x.FooList.Any(s => s.Value.StartsWith(y))));

I have this error : "Can't extract value from expression of type: Parameter"

For information, if i use just the first item of tableStrings, it is ok :

query = query.Where(x => x.FooList.Any(y => y.Value.StartsWith(tableStrings.First())));
Fedor Hajdu
  • 4,657
  • 3
  • 32
  • 50
k4st0r42
  • 1,174
  • 1
  • 15
  • 29

1 Answers1

2

You could do that efficiently by using an index:

public class ObjektFooListIndex : AbstractIndexCreationTask<Objekt, ObjektFooListIndex.Result> {

    public class Result {
        public string[] Values;
    }

    public ObjektFooListIndex() {
        Map = objekts => from objekt in objekts
                         select new {
                             Values = objekt.FooList.Select(x => x.Value).ToArray()
                         };

        Index(x => x.Values, Raven.Abstractions.Indexing.FieldIndexing.NotAnalyzed);
    }
}

Now you can search for the contents of the Foo.Value strings:

var result = session.Query<ObjektFooListIndex.Result, ObjektFooListIndex>()
    .Search(x => x.Values, "ein*", escapeQueryOptions: EscapeQueryOptions.AllowPostfixWildcard)
    .AsProjection<Objekt>()
    .ToList();

Thre result will be a list of Objekt. To search for multiple terms use Search() multiple times.

var result = session.Query<ObjektFooListIndex.Result, ObjektFooListIndex>()
    .Search(x => x.Values, "ein*", escapeQueryOptions: EscapeQueryOptions.AllowPostfixWildcard, options: SearchOptions.Or)
    .Search(x => x.Values, "dr*", escapeQueryOptions: EscapeQueryOptions.AllowPostfixWildcard, options: SearchOptions.Or)
    .AsProjection<Objekt>()
    .ToList();

You could easily extend this for your needs.

To create the Index use IndexCreation.CreateIndexes().

dusky
  • 1,133
  • 7
  • 12
  • Your solution may be good, but not in my case because I can't use Search() with wildcards. I don't know why but it doesn't work with my strings. Example to match the string "uri:fooA:fooB:123.456.789" : Wilcards "uri:*" or "uri:fooA:" or "uri:fooA:fooB:" will work, but wilcards "uri:fooA:fooB:123.*" or "uri:fooA:fooB:123.456.*" will not work. Do you have an other solution ? – k4st0r42 Nov 18 '14 at 13:13
  • 1
    @k4st0r42 Fixed the code, try it again. I think it was the analyzers fault. – dusky Nov 18 '14 at 13:29
  • No, it doesn't work. I have the problem of wildcard in the Search() method I explained in my previous comment. I think the cause of the issue is the numbers used in my search string (in my wildcard). – k4st0r42 Nov 20 '14 at 16:49
  • @k4st0r42 I tested the corrected code with 'uri:fooA:fooB:123.*' and 'uri:fooA:fooB:123.456.*'. It worked. Are you using a current version? Better report a bug on the [RavenDB mailing list](https://groups.google.com/forum/#!forum/ravendb). – dusky Nov 20 '14 at 21:52
  • You was right, with the "KeywordAnalyzer" it is better. But i can't see the modification in your example. – k4st0r42 Nov 21 '14 at 08:06