Mongodb返回多个子数组结果并排除其他返回结果
Mongodb returning multiple sub array results and excluding other returned results
我有以下带有节点数组的集合:
{
"_id" : ObjectId("55acf6187d4c31475417fa62"),
"node" : [
{
"-id" : "29331496",
"-uid" : "1899168",
"-changeset" : "26313303",
"-lat" : "-37.6104102",
"-lon" : "144.9459817",
"-timestamp" : "2014-10-25T03:36:51Z",
"-user" : "heyitsstevo",
"-visible" : "true",
"-version" : "6"
},
{
"-id" : "29331497",
"-uid" : "1899168",
"-version" : "2",
"-lon" : "144.9451088",
"-timestamp" : "2014-10-25T03:36:51Z",
"-user" : "heyitsstevo",
"-visible" : "true",
"-changeset" : "26313303",
"-lat" : "-37.601881"
},
{
"-id" : "29331498",
"-timestamp" : "2014-10-25T03:36:51Z",
"-version" : "3",
"-uid" : "1899168",
"-user" : "heyitsstevo",
"-visible" : "true",
"-changeset" : "26313303",
"-lat" : "-37.6011267",
"-lon" : "144.9448575"
},
{
"-lon" : "144.943302",
"-id" : "29331499",
"-timestamp" : "2011-11-23T03:21:40Z",
"-user" : "melb_guy",
"-version" : "9",
"-uid" : "11111",
"-visible" : "true",
"-changeset" : "9916439",
"-lat" : "-37.5983291"
},
{
"-id" : "60648717",
"-uid" : "46482",
"-user" : "Zulu99",
"-lat" : "-37.6796337",
"-lon" : "144.9220639",
"-timestamp" : "2009-12-12T21:29:36Z",
"-visible" : "true",
"-version" : "2",
"-changeset" : "3358816"
},
{
"-id" : "60648718",
"-timestamp" : "2009-12-12T21:29:35Z",
"-uid" : "46482",
"-version" : "2",
"-changeset" : "3358816",
"-user" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.6787103",
"-lon" : "144.9224609"
},
{
"-id" : "60648719",
"-timestamp" : "2009-12-12T21:28:58Z",
"-user" : "Leon K",
"-version" : "2",
"-changeset" : "3358816",
"-uid" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.677841",
"-lon" : "144.9227344"
}
]
}
如何 return 所有具有“-user” = "Zulu99" 的节点并排除其他任何内容?
我尝试了以下查询,但它只是 return 它找到的第一个节点 "Zulu99":
db.osm.find( { }, { node: {$elemMatch: {'-user': 'Zulu99'}}} )
你需要的是"aggregation" and the $map
and the $setDifference
个运算符
db.collection.aggregate([
{
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
},
{
"$project": {
"node": {
"$setDifference": [{
"$map": {
"input": "$node",
"as": "n",
"in": {
"$cond": [
{ "$eq": [ "$$n.-user", "Zulu99" ]},
"$$n",
false
]
}
}
},
[false]]
}
}
}
])
从 MongoDB 3.2 开始,您可以使用 $filter
运算符
db.collection.aggregate([
{
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
},
{ "$project": {
"node": {
"$filter": {
"input": "$node",
"as": "n",
"cond": { "$eq": [ "$$node.n", "Zulu99" ] }
}
}
}}
])
产生:
{
"_id" : ObjectId("55acf6187d4c31475417fa62"),
"node" : [
{
"-id" : "60648717",
"-uid" : "46482",
"-user" : "Zulu99",
"-lat" : "-37.6796337",
"-lon" : "144.9220639",
"-timestamp" : "2009-12-12T21:29:36Z",
"-visible" : "true",
"-version" : "2",
"-changeset" : "3358816"
},
{
"-id" : "60648718",
"-timestamp" : "2009-12-12T21:29:35Z",
"-uid" : "46482",
"-version" : "2",
"-changeset" : "3358816",
"-user" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.6787103",
"-lon" : "144.9224609"
}
]
}
如果您的文档大小超过 aggregation
$unwind
会创建 Cartesian Product problem i.e every array object creates multiple documents so it creates slow down aggregation query, If you want avoid this problem use $redact,如下所示:
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99"
}
}, {
"$redact": {
"$cond": {
"if": {
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}).pretty()
编辑
如果你想要多个条件,那么使用 $cond
和 $and
像这样
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
}, {
"$redact": {
"$cond": {
"if": {
"$and": [{
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
}, {
"$eq": [{
"$ifNull": ["$-lat", "-37.6787103"]
}, "-37.6787103"]
}]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}).pretty()
在上面的查询中你得到 lat
检查是否等于 -37.6787103
或不,如果你想检查 -lat and -lon
到 $gt or $lt
然后首先你应该改变您的文档中 lat and lon
的数据类型看起来像 String
所以首先更改数据类型 String to number
然后使用 comparison operator.
第二件事,如果你只想匹配 node
数组对象,然后在 readact
之后使用 group
,就像这样:
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
}, {
"$redact": {
"$cond": {
"if": {
"$and": [{
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
}, {
"$eq": [{
"$ifNull": ["$-lat", "-37.6787103"]
}, "-37.6787103"]
}]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}, {
"$group": {
"_id": "$_id",
"node": {
"$first": "$node" // use $first
}
}
}).pretty()
新编辑
如果您想找出 gte and lte
条件,请遵循此聚合:
db.collectionName.aggregate({
"$project": {
"check": {
"$setDifference": [{
"$map": {
"input": "$node",
"as": "node1",
"in": {
"$cond": {
"if": {
"$and": [{
"$and": [{
"$gte": ["$$node1.-lon", 100]
}, {
"$lte": ["$$node1.-lon", 150]
}]
}, {
"$and": [{
"$gte": ["$$node1.-lat", -50]
}, {
"$lte": ["$$node1.-lat", -10]
}]
}]
},
"then": "$$node1",
"else": false
}
}
}
},
[false]
]
}
}
}).pretty()
我有以下带有节点数组的集合:
{
"_id" : ObjectId("55acf6187d4c31475417fa62"),
"node" : [
{
"-id" : "29331496",
"-uid" : "1899168",
"-changeset" : "26313303",
"-lat" : "-37.6104102",
"-lon" : "144.9459817",
"-timestamp" : "2014-10-25T03:36:51Z",
"-user" : "heyitsstevo",
"-visible" : "true",
"-version" : "6"
},
{
"-id" : "29331497",
"-uid" : "1899168",
"-version" : "2",
"-lon" : "144.9451088",
"-timestamp" : "2014-10-25T03:36:51Z",
"-user" : "heyitsstevo",
"-visible" : "true",
"-changeset" : "26313303",
"-lat" : "-37.601881"
},
{
"-id" : "29331498",
"-timestamp" : "2014-10-25T03:36:51Z",
"-version" : "3",
"-uid" : "1899168",
"-user" : "heyitsstevo",
"-visible" : "true",
"-changeset" : "26313303",
"-lat" : "-37.6011267",
"-lon" : "144.9448575"
},
{
"-lon" : "144.943302",
"-id" : "29331499",
"-timestamp" : "2011-11-23T03:21:40Z",
"-user" : "melb_guy",
"-version" : "9",
"-uid" : "11111",
"-visible" : "true",
"-changeset" : "9916439",
"-lat" : "-37.5983291"
},
{
"-id" : "60648717",
"-uid" : "46482",
"-user" : "Zulu99",
"-lat" : "-37.6796337",
"-lon" : "144.9220639",
"-timestamp" : "2009-12-12T21:29:36Z",
"-visible" : "true",
"-version" : "2",
"-changeset" : "3358816"
},
{
"-id" : "60648718",
"-timestamp" : "2009-12-12T21:29:35Z",
"-uid" : "46482",
"-version" : "2",
"-changeset" : "3358816",
"-user" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.6787103",
"-lon" : "144.9224609"
},
{
"-id" : "60648719",
"-timestamp" : "2009-12-12T21:28:58Z",
"-user" : "Leon K",
"-version" : "2",
"-changeset" : "3358816",
"-uid" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.677841",
"-lon" : "144.9227344"
}
]
}
如何 return 所有具有“-user” = "Zulu99" 的节点并排除其他任何内容?
我尝试了以下查询,但它只是 return 它找到的第一个节点 "Zulu99":
db.osm.find( { }, { node: {$elemMatch: {'-user': 'Zulu99'}}} )
你需要的是"aggregation" and the $map
and the $setDifference
个运算符
db.collection.aggregate([
{
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
},
{
"$project": {
"node": {
"$setDifference": [{
"$map": {
"input": "$node",
"as": "n",
"in": {
"$cond": [
{ "$eq": [ "$$n.-user", "Zulu99" ]},
"$$n",
false
]
}
}
},
[false]]
}
}
}
])
从 MongoDB 3.2 开始,您可以使用 $filter
运算符
db.collection.aggregate([
{
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
},
{ "$project": {
"node": {
"$filter": {
"input": "$node",
"as": "n",
"cond": { "$eq": [ "$$node.n", "Zulu99" ] }
}
}
}}
])
产生:
{
"_id" : ObjectId("55acf6187d4c31475417fa62"),
"node" : [
{
"-id" : "60648717",
"-uid" : "46482",
"-user" : "Zulu99",
"-lat" : "-37.6796337",
"-lon" : "144.9220639",
"-timestamp" : "2009-12-12T21:29:36Z",
"-visible" : "true",
"-version" : "2",
"-changeset" : "3358816"
},
{
"-id" : "60648718",
"-timestamp" : "2009-12-12T21:29:35Z",
"-uid" : "46482",
"-version" : "2",
"-changeset" : "3358816",
"-user" : "Zulu99",
"-visible" : "true",
"-lat" : "-37.6787103",
"-lon" : "144.9224609"
}
]
}
如果您的文档大小超过 aggregation
$unwind
会创建 Cartesian Product problem i.e every array object creates multiple documents so it creates slow down aggregation query, If you want avoid this problem use $redact,如下所示:
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99"
}
}, {
"$redact": {
"$cond": {
"if": {
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}).pretty()
编辑
如果你想要多个条件,那么使用 $cond
和 $and
像这样
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
}, {
"$redact": {
"$cond": {
"if": {
"$and": [{
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
}, {
"$eq": [{
"$ifNull": ["$-lat", "-37.6787103"]
}, "-37.6787103"]
}]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}).pretty()
在上面的查询中你得到 lat
检查是否等于 -37.6787103
或不,如果你想检查 -lat and -lon
到 $gt or $lt
然后首先你应该改变您的文档中 lat and lon
的数据类型看起来像 String
所以首先更改数据类型 String to number
然后使用 comparison operator.
第二件事,如果你只想匹配 node
数组对象,然后在 readact
之后使用 group
,就像这样:
db.collectionName.aggregate({
"$match": {
"node.-user": "Zulu99",
"node.-lat": "-37.6787103"
}
}, {
"$redact": {
"$cond": {
"if": {
"$and": [{
"$eq": [{
"$ifNull": ["$-user", "Zulu99"]
}, "Zulu99"]
}, {
"$eq": [{
"$ifNull": ["$-lat", "-37.6787103"]
}, "-37.6787103"]
}]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}
}, {
"$group": {
"_id": "$_id",
"node": {
"$first": "$node" // use $first
}
}
}).pretty()
新编辑
如果您想找出 gte and lte
条件,请遵循此聚合:
db.collectionName.aggregate({
"$project": {
"check": {
"$setDifference": [{
"$map": {
"input": "$node",
"as": "node1",
"in": {
"$cond": {
"if": {
"$and": [{
"$and": [{
"$gte": ["$$node1.-lon", 100]
}, {
"$lte": ["$$node1.-lon", 150]
}]
}, {
"$and": [{
"$gte": ["$$node1.-lat", -50]
}, {
"$lte": ["$$node1.-lat", -10]
}]
}]
},
"then": "$$node1",
"else": false
}
}
}
},
[false]
]
}
}
}).pretty()