Mongodb 如何选择数组项包含在数组值中的文档?
我在mongodb(3.0)中有收藏: 我想查找具有m属性的文档,其中m._t包含['type1','type2'] 像这样:Mongodb 如何选择数组项包含在数组值中的文档?,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我在mongodb(3.0)中有收藏: 我想查找具有m属性的文档,其中m._t包含['type1','type2'] 像这样: { _id: 1, m: [{_id:11, _t: 'type1'}, {_id:12, _t: 'type2'}] }, { _id: 2, m: [{_id:21, _t: 'type1'}] } 我尝试使用$and$elemMatch,但无法获得所需的结果。 如何使用find()执行此操作? 请帮帮我
{
_id: 1,
m: [{_id:11, _t: 'type1'},
{_id:12, _t: 'type2'}]
},
{
_id: 2,
m: [{_id:21, _t: 'type1'}]
}
我尝试使用$and$elemMatch,但无法获得所需的结果。
如何使用find()执行此操作?
请帮帮我!谢谢 由于运算符将查询结果中m
数组字段的内容限制为仅包含与条件匹配的第一个元素,因此以下操作将仅返回具有第一个匹配元素的数组
{
"_id" : 11,
"_t" : "type1"
}
及
使用投影进行查询:
db.collection.find(
{
"m._t": {
"$in": ["type1", "type2"]
}
},
{
"m": {
"$elemMatch": {
"_t": {
"$in": ["type1", "type2"]
}
}
}
}
)
结果:
/* 0 */
{
"_id" : 1,
"m" : [
{
"_id" : 11,
"_t" : "type1"
}
]
}
/* 1 */
{
"_id" : 2,
"m" : [
{
"_id" : 21,
"_t" : "type1"
}
]
}
您可以采取的一种方法是,其中管道将由一个操作符组成,类似于上面的find查询来过滤初始文档流。下一个管道步骤将是关键的操作符,它使用另一个操作符“拆分”要进一步精简的数组元素,然后是最后的管道,通过使用累加器操作符恢复原始数据结构
以下说明了此路径:
db.collection.aggregate([
{
"$match": {
"m._t": {
"$in": ["type1", "type2"]
}
}
},
{
"$unwind": "$m"
},
{
"$match": {
"m._t": {
"$in": ["type1", "type2"]
}
}
},
{
"$group": {
"_id": "$_id",
"m": {
"$push": "$m"
}
}
}
])
样本输出:
/* 0 */
{
"result" : [
{
"_id" : 2,
"m" : [
{
"_id" : 21,
"_t" : "type1"
}
]
},
{
"_id" : 1,
"m" : [
{
"_id" : 11,
"_t" : "type1"
},
{
"_id" : 12,
"_t" : "type2"
}
]
}
],
"ok" : 1
}
要获得“过滤”的结果,使用聚合管道是最快的方法:
db.junk.aggregate([
{“$match”:{“m.\u t”:{“$in”:[“type1”,“type2”]}},
{“$redact”:{
“$cond”:{
“如果”:{
“$or”:[
{“$eq”:[{“$ifNull”:[“$\t”,“type1”]},“type1”]},
{“$eq”:[{“$ifNull”:[“$\t”,“type2”]},“type2”]}
],
},
“然后”:“$$down”,
“else”:“$$PRUNE”
}
}}
])
$redact
操作符为文档设置逻辑过滤器,该过滤器也可以遍历到数组级别。请注意,这在文档的所有级别上都是匹配的,因此请确保没有其他元素共享此名称
查询用于选择,就像逻辑筛选器使用一样。任何不匹配的内容都会被“删减”
{
“_id”:1,
“m”:[
{
“_id”:11,
_t:“类型1”
},
{
“_id”:12,
_t:“类型2”
}
]
}
{
“_id”:2,
“m”:[{u id:21,”“t”:“type1”}]
}
简短、甜蜜、简单
有点麻烦,但比较安全的方法是使用此构造并过滤结果:
db.junk.aggregate([
{“$match”:{“m.\u t”:{“$in”:[“type1”,“type2”]}},
{“$project”:{
“m”:{
“$setDifference”:[
{“$map”:{
“输入”:“$m”,
“as”:“el”,
“在”:{
“$cond”:{
“如果”:{
“$or”:[
{“$eq”:[“$$el._t”,“type1”]},
{“$eq”:[“$$el.\u t”,“type2”]}
]
},
“然后”:“$$el”,
“else”:false
}
}
}},
[错误]
]
}
}}
])
$map
针对每个元素计算条件,而$setDifference
删除返回false
而非数组内容的任何条件。非常类似于上面的修订版,但它只是专门处理一个数组,而不是整个文档
在未来的MongoDB版本中(目前在开发版本中可用),将有$filter
操作符,这非常简单:
db.junk.aggregate([
{“$match”:{“m.\u t”:{“$in”:[“type1”,“type2”]}},
{“$project”:{
“m”:{
“$filter”:{
“输入”:“$m”,
“as”:“el”,
“条件”:{
“$or”:[
{“$eq”:[“$$el._t”,“type1”]},
{“$eq”:[“$$el.\u t”,“type2”]}
]
}
}
}
}}
])
这将简单地删除任何与指定条件不匹配的数组元素
如果要在服务器上筛选数组内容,聚合框架是一种方法
db.collection.aggregate([
{
"$match": {
"m._t": {
"$in": ["type1", "type2"]
}
}
},
{
"$unwind": "$m"
},
{
"$match": {
"m._t": {
"$in": ["type1", "type2"]
}
}
},
{
"$group": {
"_id": "$_id",
"m": {
"$push": "$m"
}
}
}
])
/* 0 */
{
"result" : [
{
"_id" : 2,
"m" : [
{
"_id" : 21,
"_t" : "type1"
}
]
},
{
"_id" : 1,
"m" : [
{
"_id" : 11,
"_t" : "type1"
},
{
"_id" : 12,
"_t" : "type2"
}
]
}
],
"ok" : 1
}