RavenDb фасетный поиск, применяя предикат к вложенным значениям в документе - PullRequest
1 голос
/ 27 октября 2011

В RavenDB я понимаю, что если вам требуется подсчитать свойства, соответствующие определенным критериям, это может быть достигнуто

  1. путем создания фасетов для имен тех свойств, которые вы хотите сгруппировать,
  2. изатем создайте индекс для вышеуказанных свойств и свойств, требуемых в предложении where.
  3. , и, наконец, отправьте запрос, используя вышеуказанный индекс.и материализовать запрос с использованием расширения ToFacets.

Но что произойдет, если в предложении where содержится предикат свойства, представляющего собой набор значений в документе?Потому что, если я добавлю вложенное свойство из коллекции в индекс для родительского документа, мой фасет рассчитывает на свойства родительского документа, которые не будут точными?

, например,

public class Camera { 
  string Make { get;set; }
  string Model { get;set; } 
  double Price { get;set; }
  IEnumerable<string> Showrooms { get;set; }
}

Myзапрос будет выглядеть

(from camera in session.Query<Camera, Camera_Facets>() 
 where camera.Price < 100 && camera.ShowRooms.Any(s => s.In("VIC", "ACT", "QLD")) 
 select new { 
       camera.Make, 
       camera.Model, 
       camera.Price}
 ).ToFacets("facets/CameraFacets");

Обновление : вот неудачный тест

[TestFixture]
public class FacetedSearchWhenQueryingNestedCollections
{
    public class Car
    {
        public Car()
        {
            Locations = new List<string>();
        }

        public string Id { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        public double Price { get; set; }
        public IEnumerable<string> Locations { get; set; }
    }

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

    private static IDocumentSession OpenSession
    {
        get { return new EmbeddableDocumentStore {RunInMemory = true}.Initialize().OpenSession(); }
    }

    [Test]
    public void CanGetFacetsWhenQueryingNesetedCollectionValues()
    {
        var cars = Builder<Car>.CreateListOfSize(50)
            .Section(0, 10)
                .With(x => x.Model = "Camry")
                .With(x => x.Make = "Toyota")
                .With(x => x.Price = 2000)
                .With(x => x.Locations = new[] {"VIC", "ACT"})
            .Section(11, 20)
                .With(x => x.Model = "Corolla")
                .With(x => x.Make = "Toyota")
                .With(x => x.Price = 1000)
                .With(x => x.Locations = new[] { "NSW", "ACT" })
            .Section(21, 30)
                .With(x => x.Model = "Rx8")
                .With(x => x.Make = "Mazda")
                .With(x => x.Price = 5000)
                .With(x => x.Locations = new[] { "ACT", "SA", "TAS" })
            .Section(31, 49)
                .With(x => x.Model = "Civic")
                .With(x => x.Make = "Honda")
                .With(x => x.Price = 1500)
                .With(x => x.Locations = new[] { "QLD", "SA", "TAS" })
            .Build();

        IDictionary<string, IEnumerable<FacetValue>> facets;

        using(var s = OpenSession)
        {
            s.Store(new FacetSetup { Id = "facets/CarFacets", Facets = new List<Facet> { new Facet { Name = "Model" }, new Facet { Name = "Make" }, new Facet { Name = "Price" } } });
            s.SaveChanges();

            IndexCreation.CreateIndexes(typeof(Car_Facets).Assembly, s.Advanced.DocumentStore);

            foreach (var car in cars)
                s.Store(car);

            s.SaveChanges();

            s.Query<Car, Car_Facets>().Customize(x => x.WaitForNonStaleResults()).ToList();

            facets = s.Query<Car, Car_Facets>()
                .Where(x => x.Price < 3000)
                .Where(x => x.Locations.Any(l => l.In("QLD", "VIC")))
                .ToFacets("facets/CarFacets");
        }

        Assert.IsNotNull(facets);
        Assert.IsTrue(facets.All(f => f.Value.Count() > 0));
        Assert.IsTrue(facets.All(f => f.Value.All(x => x.Count > 0)));
    }

    [TearDown]
    public void ClearData()
    {
        using(var s = OpenSession)
        {
            foreach (var car in s.Query<Car>().ToList())
                s.Delete(car);

            s.SaveChanges();
        }
    }
}

Но если я изменю свой запрос на.(больше не запрашивая вложенную коллекцию)

    facets = s.Query<Car, Car_Facets>()
                .Where(x => x.Price < 3000)
                .ToFacets("facets/CarFacets");

Теперь я получаю 3 Перечисления в словаре, все со значениями.

1 Ответ

2 голосов
/ 28 октября 2011

если я изменю свой индекс на

    public class Car_Facets : AbstractIndexCreationTask<Car>
    {
        public Car_Facets()
        {
            Map = cars => from car in cars
                          from location in car.Locations
                          select new {car.Make, car.Model, car.Price, Location = location};
        }
    }

Создать класс для проекции

    public class CarOnLocation
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public double Price { get; set; }
        public string Location { get; set; }
    }

А затем запросить как

    facets = s.Query<Car, Car_Facets>().AsProjection<CarOnLocation>()
                .Where(x => x.Price < 3000)
                .Where(x => x.Location.In("QLD", "VIC"))
                .ToFacets("facets/CarFacets");

это работает.

...