Mapreduce 通过对文档上的嵌套值应用谓词进行RavenDb分面搜索

Mapreduce 通过对文档上的嵌套值应用谓词进行RavenDb分面搜索,mapreduce,ravendb,faceted-search,Mapreduce,Ravendb,Faceted Search,在RavenDB中,我理解当您需要计算符合特定标准的属性时,这是可以实现的 通过针对要分组的属性名称创建面 然后在上述属性和where子句中所需的属性上创建索引 最后使用上述索引发出查询。以及使用ToFacets扩展实现查询 但是,当where子句恰好包含一个针对文档上值集合的属性的谓词时,会发生什么情况呢?因为如果我将集合中的嵌套属性添加到父文档的索引中,父文档中属性的方面计数将不准确 例如 public class Camera { string Make { get;set; }

在RavenDB中,我理解当您需要计算符合特定标准的属性时,这是可以实现的

  • 通过针对要分组的属性名称创建面
  • 然后在上述属性和where子句中所需的属性上创建索引
  • 最后使用上述索引发出查询。以及使用ToFacets扩展实现查询
  • 但是,当where子句恰好包含一个针对文档上值集合的属性的谓词时,会发生什么情况呢?因为如果我将集合中的嵌套属性添加到父文档的索引中,父文档中属性的方面计数将不准确

    例如

    public class Camera { 
      string Make { get;set; }
      string Model { get;set; } 
      double Price { get;set; }
      IEnumerable<string> Showrooms { get;set; }
    }
    
    公共类摄像机{
    字符串Make{get;set;}
    字符串模型{get;set;}
    双倍价格{get;set;}
    IEnumerable展厅{get;set;}
    }
    
    我的查询看起来像

    (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");
    
    (来自会话中的摄影机。查询()
    其中camera.Price<100&&camera.shourrooms.Any(s=>s.In(“VIC”、“ACT”、“QLD”))
    选择新{
    照相机,制造,
    相机,模型,
    相机价格}
    ).ToFacets(“刻面/摄像机”);
    
    更新: 这是失败的测试

    [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();
            }
        }
    }
    
    [TestFixture]
    公共类FacetedSearchWhenQueryingNestedCollections
    {
    公车
    {
    公共汽车
    {
    位置=新列表();
    }
    公共字符串Id{get;set;}
    公共字符串Make{get;set;}
    公共字符串模型{get;set;}
    公共双价{get;set;}
    公共IEnumerable位置{get;set;}
    }
    公共类汽车方面:AbstractIndexCreationTask
    {
    公共汽车
    {
    地图=汽车=>从汽车中的汽车
    选择new{car.Make,car.Model,car.Price};
    }
    }
    私有静态IDocumentSession OpenSession
    {
    获取{return new embeddedabledocumentstore{RunInMemory=true}.Initialize().OpenSession();}
    }
    [测试]
    查询NeseedCollectionValues()时的公共无效存储面
    {
    var cars=Builder.CreateListOfSize(50)
    .第(0、10)节
    .带有(x=>x.Model=“凯美瑞”)
    .With(x=>x.Make=“丰田”)
    (x=>x.价格=2000)
    .With(x=>x.Locations=new[]{“VIC”,“ACT”})
    .第(11、20)条
    .With(x=>x.Model=“Corolla”)
    .With(x=>x.Make=“丰田”)
    .有(x=>x.价格=1000)
    .With(x=>x.Locations=new[]{“NSW”,“ACT”})
    .第(21、30)条
    .With(x=>x.Model=“Rx8”)
    .带有(x=>x.Make=“马自达”)
    .有(x=>x.价格=5000)
    .With(x=>x.Locations=new[]{“ACT”、“SA”、“TAS”})
    .第(31、49)条
    .With(x=>x.Model=“Civic”)
    .带有(x=>x.Make=“本田”)
    .有(x=>x.价格=1500)
    .With(x=>x.Locations=new[]{“QLD”、“SA”、“TAS”})
    .Build();
    词典方面;
    使用(var s=OpenSession)
    {
    s、 存储(新FacetSetup{Id=“facets/CarFacets”,facets=newlist{newfacet{Name=“Model”},newfacet{Name=“Make”},newfacet{Name=“Price”}});
    s、 保存更改();
    CreateIndexes(typeof(Car_Facets).Assembly,s.Advanced.DocumentStore);
    foreach(车辆中的var车辆)
    s、 商店(汽车);
    s、 保存更改();
    s、 Query().Customize(x=>x.WaitForNonStaleResults()).ToList();
    facets=s.Query()
    .其中(x=>x.价格<3000)
    .其中(x=>x.Locations.Any(l=>l.In(“QLD”、“VIC”))
    .ToFacets(“镶嵌面/镶嵌面”);
    }
    Assert.IsNotNull(facets);
    IsTrue(facets.All(f=>f.Value.Count()>0));
    IsTrue(facets.All(f=>f.Value.All(x=>x.Count>0));
    }
    [撕裂]
    public void ClearData()
    {
    使用(var s=OpenSession)
    {
    foreach(s.Query().ToList()中的var car)
    s、 删除(car);
    s、 保存更改();
    }
    }
    }
    
    但如果我将我的查询更改为。(不再查询嵌套集合)

    facets=s.Query()
    .其中(x=>x.价格<3000)
    .ToFacets(“镶嵌面/镶嵌面”);
    

    现在我在字典中得到了3个枚举,都有值。

    如果我将索引更改为

        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};
            }
        }
    
    然后查询为

        facets = s.Query<Car, Car_Facets>().AsProjection<CarOnLocation>()
                    .Where(x => x.Price < 3000)
                    .Where(x => x.Location.In("QLD", "VIC"))
                    .ToFacets("facets/CarFacets");
    
    facets=s.Query().AsProjection()
    .其中(x=>x.价格<3000)
    .Where(x=>x.Location.In(“QLD”、“VIC”))
    .ToFacets(“镶嵌面/镶嵌面”);
    

    它起作用了

    这实际上应该工作得很好,你真的看到这个返回错误的结果吗?你有一个失败的测试要发布吗?@AyendeRahien我已经更新了这个问题以提供一个失败的测试。
        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");