Mongodb 如何让mongo只返回字段中的数组?
假设以下集合定义,其中示例为此类集合中的一个条目:Mongodb 如何让mongo只返回字段中的数组?,mongodb,mongodb-query,Mongodb,Mongodb Query,假设以下集合定义,其中示例为此类集合中的一个条目: enumeration : { name: 'enumeration-1' elements: [ { value: 'value-1' tags: ['tag-1', 'tag-2'] }, { value: 'value-2', tags: ['tag-2', 'tag'-3']
enumeration : {
name: 'enumeration-1'
elements: [
{
value: 'value-1'
tags: ['tag-1', 'tag-2']
},
{
value: 'value-2',
tags: ['tag-2', 'tag'-3']
},
{
value: 'value-3'
tags: ['tag-3', 'tag-4']
}
]
}
返回特定枚举非常简单:
db.enumerations.find({ name: 'enumeration-1' })
但是,我需要扩展该查询,以仅返回每个元素在标记列表中至少有一个标记的元素。考虑以下参数:
1. name: 'enumeration-1'
2. tags: ['tag-1', 'tag-4']
我需要输出为:
['value-1', 'value-3']
也就是说,我只需要具有枚举1中包含的一个或多个指定标记的元素的值。如果可能的话,查询会是什么样子?返回完整元素也可以。我正在使用Mongo2.6.9 不确定这是否有效(从内存中),但似乎需要查看数组查询的$elemMatch,然后查看要查找的第二个可选参数,即用于投影的参数
db.enumerations.find({ name: 'enumeration-1', elements : {$elemMatch : { $in : ['tag-1', 'tag-4']}}}, {_id:0, 'elements.value':1})
您可以运行以下聚合操作,将其用作hack(脏操作)来生成修剪后的元素数组:
var query = {
"name": "enumeration-1",
"tags": ["tag-1", "tag-4"]
};
db.enumerations.aggregate([
{ "$match": { "name": query.name } },
{
"$project": {
"name": 1,
"elements": {
"$setDifference": [
{
"$map": {
"input": "$elements",
"as": "el",
"in": {
"$cond": [
{
"$setEquals": [
{
"$setIntersection": [
"$$el.tags", query.tags
]
},
[]
]
},
false,
"$$el"
]
}
}
},
[false]
]
}
}
}
])
您可以使用聚合框架。find查询中的另一种选择是,或者两者都只支持返回数组中的第一个匹配元素,因此它们不适用于您的案例,因为您需要所有的值,而且它们无论如何也不适用于您的案例(我认为)。您需要按数组值进行筛选,但需要投影其他内容 但这里是它如何在聚合框架中工作的(如果需要,您最终可以做各种事情,例如使结果独特等) 这个函数的输出如下所示
{
"values" : [ "value-1", "value-3"]
}
我会相应地更正这个问题。然而,我指的是你的第一个例子。我相信这个查询很接近,但没有返回任何结果。我想知道这是否是因为“tags”属性上没有限定符。我修改了查询,使其看起来像是
db.enumerations.find({name:'enumeration-1',elements:{$elemMatch:{tags:{$elemMatch:{$in:{['tags-1','tags-4']}}})
。但是,它返回所有值(包括不期望的值-2)。@predhme是否愿意告诉我您为什么不接受此答案?这将给我建设性的批评,这将使我能够更好地在未来框架我的答案。当我最初接受这个答案时,我在Mongo控制台内测试,这对我来说很好。但是,当我将查询放入Jongo(我们的mongo框架)时,查询没有得到正确解析,这是没有明显原因的。我搜索了他们的文档并尝试了很多方法,但是当从Jongo运行时,查询失败了。我使用的java驱动程序是2.6.9,它与Mongo verison相匹配。我使用的是Jongo 1.2。感谢您的澄清:)我当然更喜欢这个答案,因为结果正好是我想要的(从mongo控制台)。然而,Jongo/mongo java驱动程序似乎不尊重$setDifference。。。我的结果如下:{“name”:“enumeration-1”,“elements”:{“$setDifference”:{…}
。我在设置的差异处停了下来,因为查询返回表达式似乎不正确……不确定为什么框架没有对其进行计算。似乎使用$unwind
是您唯一的选择,因为它会为每个数组条目生成每个文档的副本。您必须小心大型数组将使用mor由于笛卡尔积(聚合管道上的内存上限可能为总内存的10%),因此也需要时间来生成和处理。
db.enumerations.aggregate([
{ $match: {"name":"enumeration-1"} },
{ $unwind: "$elements" },
{ $unwind: "$elements.tags" },
{ $match: {"elements.tags": { $in:["tag-1","tag-4"] } }},
{ $group : { _id : null, values: { $push: "$elements.value" } } },
{ $project: {"_id":0, values:1}}
])
{
"values" : [ "value-1", "value-3"]
}