RavenDB:如何在多地图索引上索引字典键?
RavenDB: How to index dictionary keys on a multi-map index?
我得到了以下有效的 RavenDB MultiMap 索引和 returns 结果。现在,当我想使用查询并尝试过滤数据时,我收到以下消息:
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)) <--
};
参见索引的动态字段 (docs)。然后我收到以下消息:
Map and Reduce functions of a index must return identical types.
我通过将 _ = (string) null
作为 属性 添加到每个 AddMap
函数来解决这个问题(不确定它是否是完美的解决方案,但是嘿,它起作用了)然后以下查询有效:
from index 'Products/SearchUniqueBySku'
where Stock_589e90c9-09bb-4a04-94fb-cf92bde88f97 > 0
您需要在索引的 Reduce
中执行此操作:
_ = grouped.SelectMany(x => CreateField("Stock_" +x.Stock.Key, x.Stock.Value))
使用 _
将字段标记为包含动态字段。
它将发出的字段格式为 Stock_$key
我得到了以下有效的 RavenDB MultiMap 索引和 returns 结果。现在,当我想使用查询并尝试过滤数据时,我收到以下消息:
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)) <--
};
参见索引的动态字段 (docs)。然后我收到以下消息:
Map and Reduce functions of a index must return identical types.
我通过将 _ = (string) null
作为 属性 添加到每个 AddMap
函数来解决这个问题(不确定它是否是完美的解决方案,但是嘿,它起作用了)然后以下查询有效:
from index 'Products/SearchUniqueBySku'
where Stock_589e90c9-09bb-4a04-94fb-cf92bde88f97 > 0
您需要在索引的 Reduce
中执行此操作:
_ = grouped.SelectMany(x => CreateField("Stock_" +x.Stock.Key, x.Stock.Value))
使用 _
将字段标记为包含动态字段。
它将发出的字段格式为 Stock_$key