yoliva
yoliva

Reputation: 51

RavenDb search over multiple string properties

I'm trying to make a search over multiple properties. I want to get all the items that at least one of its properties contains the specified term. The following code works as expected but I would like to achieve this using Search instead of a Lucene query.

var t = Regex.Replace(term, " ", @"\ ");
var query = session.Advanced
  .DocumentQuery<Order>()
  .Where($"Property1:*{t}* OR Property2:*{t}* OR Property3:*{t}*");

Upvotes: 2

Views: 494

Answers (2)

yoliva
yoliva

Reputation: 51

It's been a while since I asked the question but in the last couple of days, I went over this again. I ended up querying in the way I show below and everything works fine.

            var search = $"\"*{term}*\"";
            var qOpt = EscapeQueryOptions.RawQuery;

            query = query
                .Search(o => o.Property1, search, escapeQueryOptions: qOpt)
                .Search(o => o.Property2, search, escapeQueryOptions: qOpt)
                .Search(o => o.Property3, search, escapeQueryOptions: qOpt)
                .Search(o => o.Property4, search, escapeQueryOptions: qOpt);

Upvotes: 0

Embri
Embri

Reputation: 622

var result = session
    .Query<Order>()
    .Search(x => x.Property1, "*term*")
    .Search(x => x.Property2, "*term*")
    .Search(x => x.Property3, "*term*")
    .ToList();

Read the docs (select your ravendb version): https://ravendb.net/docs/article-page/4.0/csharp/indexes/querying/searching

From RavenDB docs:

"By default, RavenDB attempts to guess and match up the semantics between terms. If there are consecutive searches, they will be OR together, otherwise the AND semantic will be used."

And also consider:

"RavenDB allows you to search by using such queries, but you have to be aware that leading wildcards drastically slow down searches.

Consider if you really need to find substrings. In most cases, looking for whole words is enough. There are also other alternatives for searching without expensive wildcard matches, e.g. indexing a reversed version of text field or creating a custom analyzer."

In previous version of RavenDB it's necessary to allow wildcards in the query:

var result = session
        .Query<Order>()
        .Search(x => x.Property1, "*term*", escapeQueryOptions: EscapeQueryOptions.AllowAllWildcards)
        .Search(x => x.Property2, "*term*", escapeQueryOptions: EscapeQueryOptions.AllowAllWildcards)
        .Search(x => x.Property3, "*term*", escapeQueryOptions: EscapeQueryOptions.AllowAllWildcards)
        .ToList();

Update after @yoliva comment:

To achieve what you want i found a workaround, it consist to replace all whitespaces with a different character in the index definition, and when you query do the same.

Index:

public class OrdersIndex : Raven.Client.Documents.Indexes.AbstractIndexCreationTask<Order>
{
     public OrdersIndex()
     {
           Map = orders => from order in orders
                           select new
                           {
                               Property1 = order.Property1.Replace(" ", "-"),
                               Property2 = order.Property2.Replace(" ", "-"),
                               Property3 = order.Property3.Replace(" ", "-"),
                           };
     }
}

query:

var result = session.Query<Order, OrdersIndex>()
                    .Search(x => x.Property1, "*me product n*".Replace(" ", "-"))
                    .Search(x => x.Property2, "*me prod*".Replace(" ", "-"))
                    .Search(x => x.Property3, "*product*".Replace(" ", "-"))
                    .ToList();

Upvotes: 2

Related Questions