7

I am trying to find all posts in RavenDB containing a word (index is there)

Here is a query that works, finds everything that starts with 'Liv'

let post = query {
    for post in session.Query<MyType>() do
    where (post.Text.StartsWith("Liv"))
    select post
}

An attempt to use string.Contains() method as condition of Where closure, will throw NotSupportedException. Here

So I am trying to use Search method where:

Expression<Func<T, object>> fieldSelector, 
// Expression marking a field in which terms should be looked for.

C# equivalent from docs:

List<User> users = session
    .Query<User>("Users/ByNameAndHobbies")
    .Search(x => x.Name, "Adam")
    .Search(x => x.Hobbies, "sport")
    .ToList();

My first try was to go with

let x = session.Query<MyType>(index).Search((fun xe -> xe.Text ), "Liv")

But getting error because it expects object out. Tried to downcast String to Object (what a strange idea), but getting:

Cannot understand how to translate x => x.Invoke(xe)

At the moment, I am out of ideas. I am supposed to mark field for search and return object. Any ideas?

Thank you.

EDIT 1: My expression. Gets runtime InvalidCastException because it can't cast string to obj.

let expr = 
  <@ Func<MyType, _>(fun xe -> xe.Text ) @>
  |> LeafExpressionConverter.QuotationToExpression 
  |> unbox<System.Linq.Expressions.Expression<Func<MyType, _>>>
Dimka
  • 425
  • 4
  • 11
  • I'm reasonably sure that `x => x.Name` in `Search` is not a `Func` but `Expression>`, so you either have to use expressions or quotations if there's F# compatible API... – Patryk Ćwiek May 15 '15 at 13:46
  • Made edit. The thing is... fun xe -> xe.Text is returning string because Text is string. But the function expects obj. Downcasting didn't worked because "Cannot understand how to translate x => x.Invoke(xe.Text)". I am very unsure what "marking a field" really means here. – Dimka May 15 '15 at 15:13
  • 1
    One option is to use the Lucene query API, which takes the property name as a string. Related: http://stackoverflow.com/questions/24625040/search-query-in-ravendb – Jay May 15 '15 at 16:30
  • It's ironical this question was asked right after Ayende wrote a blog post against F#: http://ayende.com/blog/170849/why-ravendb-isnt-written-in-f-or-the-cost-of-the-esoteric-choice – SiberianGuy May 16 '15 at 10:13
  • @Idsa He has a good point, he is not against F#, but against rewriting db to F#. I am using a couple of C# libs without any problem and that was the idea behind .Net. Write in any language and use in any other .Net language. However, they should have code examples of basic things like connection and setup. Samples I am using are from v1 or smth (3.0 latest). – Dimka May 16 '15 at 15:30

1 Answers1

4

You mentioned that you tried casting the string to object. I tried it using :> obj and it does work.

Here is my working query:

let expr = <@ Func<MyType,_>(fun x -> x.Text :> obj ) @>
                |> LeafExpressionConverter.QuotationToExpression
                |> unbox<Linq.Expressions.Expression<Func<MyType,_>>>
let events = session.Query<MyType>()
                .Search(expr, "Liv*", decimal 1, SearchOptions.Or, EscapeQueryOptions.AllowAllWildcards)
                |> List.ofSeq
Jay
  • 56,361
  • 10
  • 99
  • 123
  • Actually, I did a multi-line cast and my version throws exception, but yours doesn't. Funny, it should be the same. Thank you for answer. <@ Func(fun x -> let xe = x.Text :> obj xe ) @> – Dimka May 15 '15 at 17:52