0
votes

I can't figure out to get my RavenDB query to work as expected.

I am trying to do an exact match based on users search query to match all the words in the string.

So when I type "Volkswagen" I want to get all types of "Volkswagen" cars. And if I type "Volkswagen Golf" I want to get only the "Volkswagen Golf" ones, and so forth..

What I have so far

public IEnumerable<Cars> GetSearch(string query)
{
    return _documentSession.Query<Car>("CarIndex").Search(x => x.SearchQuery, query);
}

//Also tried with this one
public IEnumerable<Cars> GetSearch(string query)
{
    return _documentSession.Query<Car>("CarIndex")
        .Search(x => x.Make, query)
        .Search(x => x.Model, query);
}


public class CarIndex : AbstractIndexCreationTask<Car>
{
    public CarIndex()
    {
        Map = cars => from car in cars select 
                new
                   {
                        car.SearchQuery, 
                        car.Make, 
                        car.Model, 
                        car.Year
                   };

        Index(x => x.Id, FieldIndexing.No);
        Index(x => x.SearchQuery, FieldIndexing.Analyzed);
        Index(x => x.Make, FieldIndexing.NotAnalyzed);
        Index(x => x.Model, FieldIndexing.NotAnalyzed);
        Index(x => x.Year, FieldIndexing.NotAnalyzed);
    }
}


private void AddDummyData()
{
    var cars = new List<Car>
    {
        new Car {Id = 1, Make = "Volkswagen", Model = "Touran", Year = 1998 },
        new Car {Id = 2, Make = "Volkswagen", Model = "Polo", Year = 2000 },
        new Car {Id = 3, Make = "Nissan", Model = "Micra", Year = 2005 },
        new Car {Id = 4, Make = "Bugatti", Model = "Veyron", Year = 2010 },
        new Car {Id = 5, Make = "Ferrari", Model = "Spider 458", Year = 2011 },
        new Car {Id = 6, Make = "Aston Martin", Model = "Vanquish", Year = 2010 },
        new Car {Id = 7, Make = "Ford", Model = "Focus", Year = 2001 },
        new Car {Id = 8, Make = "Fiat", Model = "Punto", Year = 2013 },
        new Car {Id = 9, Make = "Peugeot", Model = "206", Year = 2006 },
        new Car {Id = 10, Make = "Opel", Model = "Ascona", Year = 2002 },
        new Car {Id = 11, Make = "Volkswagen", Model = "Golf", Year = 1997 }
    };


    foreach (var car in cars)
    {
        car.SearchQuery = car.Make + " " + car.Model;
        _documentSession.Store(car);
    }

    _documentSession.SaveChanges();
}

The problem is when the make contains two words: "Aston Martin" etc.. Can someone fill me in what I'm missing?

1

1 Answers

1
votes

I believe it is because of your Lucene. With just the FieldIndexing.Analyzed it assumes that you want to tokenize using the StandardAnalyzer. So when you pass in multiple words it will find anything that matches any of those words.

Since you want all words to be matched you could do something like

var search = string.Join(" ", query
      .Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
      .Select(x => string.Format("{0}* ", x)));

query =
    _documentSession.Query<Car>("CarIndex")
            .Statistics(out stats)
            .Search(x => x.SearchQuery, search, 10, SearchOptions.And, EscapeQueryOptions.AllowPostfixWildcard)

Or you can change your Analyzer

http://ravendb.net/docs/client-api/querying/static-indexes/configuring-index-options