在 RavenDB 中通过多个值查询子集合 [英] Querying a child collection by multiple values in RavenDB

查看:18
本文介绍了在 RavenDB 中通过多个值查询子集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 RavenDB build 371,我有以下模型:

I'm using RavenDB build 371 and I have the following model:

class Product {
 public string Id { get; set; }
 public ProductSpec[] Specs { get; set; }
}

class ProductSpec {
 public string Name { get; set; }
 public string Value { get; set; }
}

我希望能够查询具有一组规格的产品.按单一规格查询时:

I would like to be able to query for products which have a set of specs. When querying by a single spec:

session.Query<Product>()
 .Where(product => product.Specs.Any(spec => spec.Name == "Color" && spec.Value == "Red"))
 .ToList();

返回预期结果,但是当添加额外的规范谓词时:

The expected results are returned, however when an additional spec predicate is added:

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 方法时会观察到相同的结果.这似乎与 这个讨论但是我无法实施建议的解决方案.具体来说,创建建议索引后,我不知道如何查询它.

no results are returned even though the results returned by the first query contain products with spec name "Country" and spec value "US". The same outcome is observed when using the LuceneQuery method. This seems to be a similar issue to this discussion however I was unable to implement to suggested solution. Specifically, after creating the suggested index, I don't know how to query it.

如何在 RavenDB 中支持这种类型的查询?

How can I support this type of query in RavenDB?

编辑

我仍然无法查询复合类型集合的多个值.相反,我更改了模型,以便规范/值组合是一个串联的字符串,这样规范集合就是一个字符串数组.这可以通过多个值来查询:

I still can't query on multiple values on a collection of compound types. Instead, I changed the model so that a spec/value combination is a concatenated string such that the specs collection is an array of strings. This can be queried by multiple values:

class Product {
 public string Id { get; set; }
 public int CategoryId { get; set; }
 public string[] Specs { get; set; }
}

作为参考,原始模型和查询在使用 MongoDB 和他们的 multikeys 索引功能.MongoDB 的一个非常令人惊讶的问题是 count() 操作 索引查询速度很慢.这种类型的查询对于分页至关重要,虽然可以缓存计数,但我想要一个开箱即用的解决方案.此外,我的另一个要求是能够为任意产品集合聚合规格组(例如,获取给定类别中产品的所有规格/价值组合的集合).在 MongoDB 中,这可以使用它们的 MapReduce 功能来实现,但是 MapReduce 操作的结果是静态的,并且必须在源数据更改时手动更新,而 RavenDB 会在后台自动更新 MapReduce 索引.因此,尽管在 RavenDB 中声明 MapReduce 索引比在 MongoDB IMO 中更麻烦,但自动后台更新远远超过了缺点.我将查看 CouchDB 因为他们的视图也会自动更新,尽管看起来它们是按需更新的,而不是自动在后台,不确定这是否会成为问题.

For reference, the original model and query works when using MongoDB with their multikeys index feature. The very surprising problem with MongoDB is that the count() operation is slow for index queries. This type of query is essential for pagination and although count can be cached I would like a solution which provides this out of the box. Also, one other requirement I have is the ability to aggregate spec groups for arbitrary collections of products (for example, to get a collection of all spec/value combinations for products in a given category). In MongoDB this can be achieved using their MapReduce functionality, however the results of a MapReduce operation are static and must be manually updated when the source data changes whereas RavenDB updates MapReduce indexes automatically in the background. So, even though declaring MapReduce indexes in RavenDB is more cumbersome than it is in MongoDB IMO, the automatic background updating outweighs the drawbacks by a long shot. I will be looking at CouchDB as their views are also updated automatically, though it appears they are updated on demand, not automatically in the background, not sure if this will be an issue.

推荐答案

我已经稍微改变了模型,并且能够使用 AbstractIndexCreationTask 中的 Project 方法达到预期的结果.这是(简化的)数据模型:

I've changed the model a bit and was able to achieve the desired result using the Project method in AbstractIndexCreationTask. This is the (simplified) data model:

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",按售出的总单位降序排列.

This will return the products in category "15920" which have a "Class" spec value of "3A" and a "Finish" spec value of "Plain" sorted in descending order by the total units sold.

关键是使用 Project 方法,该方法基本上在 Lucene 文档中为每个规范名称-值对创建字段.

The key was using the Project method which basically creates fields in the Lucene document for each spec name-value pair.

这篇关于在 RavenDB 中通过多个值查询子集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆