RavenDB:如何在多映射索引上索引字典键?

4

我有以下工作并返回结果的RavenDB MultiMap索引。现在当我想要使用查询并尝试过滤数据时,我会得到以下消息:

The field 'Stock_Key' is not indexed, cannot query/sort on fields that are not indexed.

我正在尝试获取所有在特定仓库有库存的产品。_request.Warehouses是可提供给查询的仓库ID列表。产品库存保存在数据库中的单独集合中,该集合保存相同SKU。

var query = await _session
    .Query<Products_SearchUniqueBySku.Result, Products_SearchUniqueBySku>()
    .Where(x => x.Stock.Any(y => y.Key.In(_request.Warehouses) && y.Value > 0))
    .ToListAsync();

我一整天都在尝试索引密钥,但没有成功。希望能得到一些帮助。我还尝试通过RavenDB工作室中的一些RQL变体进行查询,但在那里得到了更多相同的消息。不确定RQL查询是否编写正确。

from index 'Products/SearchUniqueBySku'
where Stock.589e90c9-09bb-4a04-94fb-cf92bde88f97 > 0

The field 'Stock.589e90c9-09bb-4a04-94fb-cf92bde88f97' is not indexed, cannot query/sort on fields that are not indexed

from index 'Products/SearchUniqueBySku'
where Stock_589e90c9-09bb-4a04-94fb-cf92bde88f97 > 0

The field 'Stock_589e90c9-09bb-4a04-94fb-cf92bde88f97' is not indexed, cannot query/sort on fields that are not indexed

我使用的索引:

using System;
using System.Collections.Generic;
using System.Linq;
using Raven.Client.Documents.Indexes;
using MyProject.Models.Ordering.Entities;
using MyProject.Models.Ordering.Enums;

namespace MyProject.Ordering.Indexes;

public class Products_SearchUniqueBySku : AbstractMultiMapIndexCreationTask<Products_SearchUniqueBySku.Result>
{
    public class Result
    {
        public string Sku { get; set; }
        public ProductTypes Type { get; set; }
        public string Name { get; set; }
        public IDictionary<string, decimal> Stock { get; set; }
    }

    public Products_SearchUniqueBySku()
    {
        AddMap<Product>(
            products => from product in products
                        where product.Type == ProductTypes.Simple
                        where product.Variants.Count == 0
                        select new
                        {
                            product.Sku,
                            product.Type,
                            product.Name,
                            Stock = new Dictionary<string, decimal>()
                        }
        );

        AddMap<Product>(
            products => from product in products
                        where product.Type == ProductTypes.Simple
                        where product.Variants.Count > 0
                        from variant in product.Variants
                        select new
                        {
                            variant.Sku,
                            Type = ProductTypes.Variant,
                            Name = $"{product.Name} ({string.Join("/", variant.Mappings.Select(y => y.Value.Name))})",
                            Stock = new Dictionary<string, decimal>()
                        });

        AddMap<StockItem>(
            items => from item in items
                     group item by item.Sku
                     into grouped
                     select new
                     {
                         Sku = grouped.Key,
                         Type = ProductTypes.Variant,
                         Name = (string) null,
                         Stock = grouped.ToDictionary(x => x.Warehouse.Id, x => x.Stock)
                     }
        );

        Reduce = results => from result in results
                            group result by result.Sku
                            into grouped
                            let product = grouped.Single(x => x.Stock.Count == 0)
                            select new
                            {
                                Sku = grouped.Key,
                                product.Type,
                                product.Name,
                                Stock = grouped.SelectMany(x => x.Stock).ToDictionary(x => x.Key, x => x.Value),
                            };
    }
}

在使用RavenDB Studio时得到的结果(只显示了部分,你可以明白):

from index 'Products/SearchUniqueBySku'

{
    "Sku": "VANS-SH-38",
    "Type": "Variant",
    "Name": "Vans Men's Suede (Maat 38)",
    "Stock": {
        "589e90c9-09bb-4a04-94fb-cf92bde88f97": 10,
        "98304a84-0f44-49ce-8438-8a959ca29b9d": 11
    },
    "@metadata": {
        "@change-vector": null,
        "@index-score": 1
    }
},
{

    "Sku": "889376",
    "Type": "Simple",
    "Name": "Apple Magic Trackpad (2021)",
    "Stock": {
        "589e90c9-09bb-4a04-94fb-cf92bde88f97": 15
    },
    "@metadata": {
        "@change-vector": null,
        "@index-score": 1
    }
}

模型(为了简洁省略大部分属性):

public class StockItem
{
    public EntityReference Warehouse { get; set; }
    public string Sku { get; set; }
    public decimal Stock { get; set; }
}

public class EntityReference
{
   public string Id { get; set; }
   public string Name { get; set; }
}

public class Product
{
   public string Id { get; set; }
   public string Name { get; set; }
   public ProductTypes Type { get; set; }
   public List<ProductVariant> Variants { get; set; }
}  

public class ProductVariant
{
   public string Sku { get; set; }
}    

编辑:

基于 @Ayende Rahien 的回答,我不得不将 Reduce 更改为以下内容:

  Reduce = results => from result in results
                    group result by result.Sku
                    into grouped
                    let product = grouped.Single(x => x.Stock.Count == 0)
                    let stock = grouped.SelectMany(x => x.Stock).ToDictionary(x => x.Key, x => x.Value)
                    select new
                    {
                        product.Id,
                        ....
                        Stock = stock,
                        _ = stock.Select(x => CreateField("Stock_" + x.Key, x.Value)) <--
                    };

请参见索引的动态字段(文档)。然后我收到了以下信息:
Map and Reduce functions of a index must return identical types.

我通过在每个AddMap函数中添加_ = (string)null属性(不确定是否是完美的解决方案,但它有效)来解决此问题,然后以下查询就可以工作:
from index 'Products/SearchUniqueBySku'
where Stock_589e90c9-09bb-4a04-94fb-cf92bde88f97 > 0
1个回答

4

您需要在索引的Reduce中执行此操作:

 _ = grouped.SelectMany(x => CreateField("Stock_" +x.Stock.Key, x.Stock.Value))

使用_标记字段以包含动态字段。它将发出的字段格式为Stock_$key


谢谢@Ayende!就是这样。不过还需要添加一些东西(请参见OP的编辑)。 - Tom Aalbers
FYI。我的错误是在StockItemAddMap函数中放置了_,而不是在Reduce中。 - Tom Aalbers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接