我在c#中的文档结构:
public class HashTableDocument : Model
{
public int Id { get; set; }
public Dictionary<string, HashSet<int>> items= new Dictionary<string, HashSet<int>>();
}
在Mongo:
{
"_id" : 218,
"items" : {
"1" : [
52711,
201610,
],
"2" : [
246421,
390200
],
"3" : [
105628,
768519
],
"26" : [
17435,
22252,
61389,
65184,
72859,
81421,
931469,
933505,
938377,
959836
],
"27" : [
26917,
38706,
53862,
111816,
827294,
858348,
870334
]
}
}
我希望能够将任何List('x')的整数传递给Mongo。如果值包含给定列表中的任何整数('x'),则仅投影那些键值对。
例如,在上面的文件中。如果我然后将List = { 52711, 105628, 17435, 81421}
传递给Mongo
它应该返回
{
"_id" : 218,
"items" : {
"1" : [
52711,
201610,
],
"3" : [
105628,
768519
],
"26" : [
17435,
22252,
61389,
65184,
72859,
81421,
931469,
933505,
938377,
959836
],
}
}
因为这些键值中的每一个都在其列表中包含至少一个元素。
答案 0 :(得分:2)
我不知道C#语法,但这里是如何使用聚合框架来完成的。请注意,这使用版本3.4.4中引入的$objectToArray
表达式。
> db.test.aggregate([{
$project: {
x: {
$filter: {
input: {$objectToArray: "$items"},
cond: {
$gt: [
{
$size: {
$filter: {
input: "$$this.v",
as: "int",
cond: {$in: ["$$int", [52711, 105628, 17435, 81421]]}
}
}
},
0
]
}
}
}
}
}])
{
"result": [
{
"_id": 218,
"items": [
{
"k": "1",
"v": [
52711,
201610
]
},
{
"k": "3",
"v": [
105628,
768519
]
},
{
"k": "26",
"v": [
17435,
22252,
61389,
65184,
72859,
81421,
931469,
933505,
938377,
959836
]
}
]
}
],
"ok": 1
}
然而,当你拥有像你这样的结构时,通常不容易进行这样的计算。此聚合不能使用任何索引来限制其搜索。您是否考虑过使用以下架构?
{
"_id": 218,
"items": [
{k: "1", v: [52711, 201610]},
{k: "2", v: [246421, 390200]},
{k: "3", v: [105628, 768519]},
{k: "26", v: [17435, 22252, 61389, 65184, 72859, 81421, 931469, 933505, 938377, 959836]},
{k: "27", v: [26917, 38706, 53862, 111816, 827294, 858348, 870334]},
]
}
然后您的问题变得更加简单,您可以执行以下操作:
db.test.aggregate([
{$match: {"items.v": {$in: [52711, 105628, 17435, 81421]}}},
{
$project: {
items: {
$filter: {
input: "$items",
cond: {
$size: {
$setIntersection:
[[52711, 105628, 17435, 81421], "$$this.v"]
}
}
}
}
}
}
])
如果您在字段&#34; items.v&#34;上创建了索引,则初始$match
阶段可以利用该索引进行更有效的查询。