我有以下带有节点数组的集合:
{
"_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"
}
]
}
如何返回具有" -user"的所有节点? =" Zulu99"并排除其他任何内容?
我尝试过以下查询,但它只返回它找到的第一个节点" Zulu99":
db.osm.find( { }, { node: {$elemMatch: {'-user': 'Zulu99'}}} )
答案 0 :(得分:2)
您需要的是"aggregation"以及$map
和$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"
}
]
}
答案 1 :(得分:0)
如果您的文档数量超过aggregation
$unwind
会产生 Cartesian Product 问题,即每个数组对象都会创建多个文档,因此会创建速度慢的聚合查询,如果您想要避免此问题,请使用 $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
,因此首先更改了数据类型node
,然后使用了comparison operator。
第二件事,如果你只想要匹配的group
数组对象,那么在readact
之后使用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()
条件,请遵循以下汇总:
public static bool TrySafeGet<T>(IList<T> list, int index, out T value)
{
value = default(T);
if (list == null || index < 0 || index >= list.Count)
{
return false;
}
value = list[index];
return true;
}