我正在使用RavenDB build 371,我有以下模型:
class Product {
public string Id { get; set; }
public ProductSpec[] Specs { get; set; }
}
class ProductSpec {
public string Name { get; set; }
public string Value { get; set; }
}
我希望能够查询具有一组规格的产品。查询单个规范时:
session.Query<Product>()
.Where(product => product.Specs.Any(spec => spec.Name == "Color" && spec.Value == "Red"))
.ToList();
返回预期结果,但是当添加其他规范谓词时:
session.Query<Product>()
.Where(product => product.Specs.Any(spec => spec.Name == "Color" && spec.Value == "Red"))
.Where(product => product.Specs.Any(spec => spec.Name == "Country" && spec.Value == "US"))
.ToList();
即使第一个查询返回的结果包含规格名称为“Country”且规格值为“US”的产品,也不会返回任何结果。使用LuceneQuery方法时会观察到相同的结果。这似乎与this discussion类似,但我无法实施建议的解决方案。具体来说,在创建建议的索引后,我不知道如何查询它。
如何在RavenDB中支持这种类型的查询?
修改
我仍然无法查询复合类型集合上的多个值。相反,我更改了模型,以便spec / value组合是一个连接的字符串,这样specs集合就是一个字符串数组。这可以通过多个值来查询:
class Product {
public string Id { get; set; }
public int CategoryId { get; set; }
public string[] Specs { get; set; }
}
作为参考,使用MongoDB及其multikeys索引功能时,原始模型和查询有效。 MongoDB的一个非常令人惊讶的问题是count()操作是slow for index queries。这种类型的查询对于分页是必不可少的,虽然可以缓存计数,但我想要一个解决方案,它提供了开箱即用的功能。此外,我的另一个要求是能够为任意产品集合聚合规范组(例如,获取给定类别中产品的所有规范/值组合的集合)。在MongoDB中,这可以使用他们的MapReduce功能来实现,但是MapReduce操作的结果是静态的,并且必须在源数据更改时手动更新,而RavenDB在后台自动更新MapReduce索引。因此,即使在RavenDB中声明MapReduce索引比在MongoDB IMO中更加繁琐,自动后台更新也远远超过了长镜头的缺点。我将查看CouchDB,因为他们的观点也会自动更新,但它们似乎是按需更新,而不是在后台自动更新,不确定这是否会成为问题。
答案 0 :(得分:3)
我尝试了不同的东西,也无法使其发挥作用。您尝试执行的特定查询由RavenDB(版本426)解析为此Lucene查询:
“{(姓名:颜色和价值:红色)和(姓名:国家和价值:美国)}”这解释了为什么没有结果。
在Google上搜索主题后,我发现了这篇文章:Lucene Query Syntax
答案中建议采用不同的解决方法。希望这会有所帮助。我自己很好奇,如果这真的不可能。
答案 1 :(得分:3)
根据构建717,您可以使用Matt Warren完成的新.Intersect()
功能执行此操作。看看这里:http://issues.hibernatingrhinos.com/issue/RavenDB-51
答案 2 :(得分:1)
我已经稍微更改了模型,并且能够使用AbstractIndexCreationTask中的Project方法实现所需的结果。这是(简化的)数据模型:
public class Product
{
public string Id { get; set; }
public int CategoryId { get; set; }
public int TotalSold { get; set; }
public Dictionary<string, string> Specs { get; set; }
}
这是索引定义:
public class Products_ByCategoryIdAndSpecs_SortByTotalSold : AbstractIndexCreationTask<Product>
{
public Products_ByCategoryIdAndSpecs_SortByTotalSold()
{
this.Map = products => from product in products
select new
{
product.CategoryId,
_ = Project(product.Specs, spec => new Field("Spec_" + spec.Key, spec.Value, Field.Store.NO, Field.Index.ANALYZED)),
product.TotalSold
};
}
}
然后我可以这样查询:
var results = session.Advanced.LuceneQuery<Product, Products_ByCategoryIdAndSpecs_SortByTotalSold>()
.WhereEquals("CategoryId", 15920)
.AndAlso().WhereEquals("Spec_Class", "3A")
.AndAlso().WhereEquals("Spec_Finish", "Plain")
.OrderBy("-TotalSold")
.ToList();
这将返回类别“15920”中的产品,其“Class”规格值为“3A”,“Finish”规格值为“Plain”,按销售总量的降序排序。
关键是使用Project
方法,该方法基本上为每个规范名称 - 值对在Lucene文档中创建字段。