仅检索MongoDB集合中对象数组中的查询元素
假设我的收藏中有以下文档:仅检索MongoDB集合中对象数组中的查询元素,mongodb,mongodb-query,aggregation-framework,projection,Mongodb,Mongodb Query,Aggregation Framework,Projection,假设我的收藏中有以下文档: { “_id”:ObjectId(“562e7c594c12942f08fe4192”), “形状”:[ { “形状”:“正方形”, “颜色”:“蓝色” }, { “形状”:“圆形”, “颜色”:“红色” } ] }, { “_id”:ObjectId(“562e7c594c12942f08fe4193”), “形状”:[ { “形状”:“正方形”, “颜色”:“黑色” }, { “形状”:“圆形”, “颜色”:“绿色” } ] } 请勿查询:
{
“_id”:ObjectId(“562e7c594c12942f08fe4192”),
“形状”:[
{
“形状”:“正方形”,
“颜色”:“蓝色”
},
{
“形状”:“圆形”,
“颜色”:“红色”
}
]
},
{
“_id”:ObjectId(“562e7c594c12942f08fe4193”),
“形状”:[
{
“形状”:“正方形”,
“颜色”:“黑色”
},
{
“形状”:“圆形”,
“颜色”:“绿色”
}
]
}
请勿查询:
db.test.find({“shapes.color”:“red”},{“shapes.color”:1})
或
db.test.find({shapes:{“$elemMatch:{color:}}},{“shapes.color”:1})
返回匹配的文档(文档1),但始终包含
形状中的所有数组项
:
{“形状”:
[
{“形状”:“方形”,“颜色”:“蓝色”},
{“形状”:“圆形”,“颜色”:“红色”}
]
}
但是,我只希望使用包含color=red
的数组获取文档(文档1):
{“形状”:
[
{“形状”:“圆形”,“颜色”:“红色”}
]
}
我该怎么做
注意:在MongoDB 2.2及更高版本的新功能推出之前,这个答案提供了一个当时相关的解决方案。如果您使用的是更新版本的MongoDB,请参阅其他答案
字段选择器参数仅限于完整属性。它不能用于选择数组的一部分,只能选择整个数组。我试着用这个,但没用
最简单的方法是只过滤客户端中的形状
如果您确实需要直接从MongoDB获得正确的输出,您可以使用map reduce来过滤形状
function map() {
filteredShapes = [];
this.shapes.forEach(function (s) {
if (s.color === "red") {
filteredShapes.push(s);
}
});
emit(this._id, { shapes: filteredShapes });
}
function reduce(key, values) {
return values[0];
}
res = db.test.mapReduce(map, reduce, { query: { "shapes.color": "red" } })
db[res.result].find()
MongoDB 2.2+中的新版本提供了Map/Reduce的替代方案。该运算符可用于将形状
数组分离为可匹配的文档流:
db.test.aggregate(
// Start with a $match pipeline which can take advantage of an index and limit documents processed
{ $match : {
"shapes.color": "red"
}},
{ $unwind : "$shapes" },
{ $match : {
"shapes.color": "red"
}}
)
结果:
{
"result" : [
{
"_id" : ObjectId("504425059b7c9fa7ec92beec"),
"shapes" : {
"shape" : "circle",
"color" : "red"
}
}
],
"ok" : 1
}
MongoDB 2.2的新投影操作符提供了另一种方法来更改返回的文档,使其仅包含第一个匹配的形状
元素:
db.test.find(
{“shapes.color”:“red”},
{{u id:0,形状:{$elemMatch:{color:“red”}});
返回:
{“形状”:[{“形状”:“圆形”,“颜色”:“红色”}]}
在2.2中,您还可以使用,其中投影对象字段名中的$
表示查询中字段的第一个匹配数组元素的索引。下面返回与上面相同的结果:
db.test.find({“shapes.color”:“red”},{u id:0,'shapes.$':1});
MongoDB 3.2更新
从3.2版本开始,您可以使用新的聚合操作符在投影期间过滤数组,这样做的好处是包括所有匹配项,而不仅仅是第一个匹配项
db.test.aggregate([
//只获取包含颜色为“红色”的shapes元素的文档
{$match:{'shapes.color':'red'},
{$项目:{
形状:{$filter:{
输入:“$shapes”,
如:‘形状’,
条件:{$eq:['$$shape.color','red']}
}},
_身份证号码:0
}}
])
结果:
[
{
“形状”:[
{
“形状”:“圆形”,
“颜色”:“红色”
}
]
}
]
与$project
一起,更合适的做法是将其他明智的匹配元素与文档中的其他元素组合在一起
db.test.aggregate(
{ "$unwind" : "$shapes" },
{ "$match" : { "shapes.color": "red" } },
{
"$project": {
"_id":1,
"item":1
}
}
)
mongodb中find的语法是
db.<collection name>.find(query, projection);
在本例中,您在查询部分使用了$elemMatch
运算符,而如果在投影部分使用此运算符,则将获得所需的结果。您可以将查询记录为
db.users.find(
{"shapes.color":"red"},
{_id:0, shapes: {$elemMatch : {color: "red"}}})
这将为您提供所需的结果。多亏了。
这里我只想添加一些更复杂的用法
// Document
{
"_id" : 1
"shapes" : [
{"shape" : "square", "color" : "red"},
{"shape" : "circle", "color" : "green"}
]
}
{
"_id" : 2
"shapes" : [
{"shape" : "square", "color" : "red"},
{"shape" : "circle", "color" : "green"}
]
}
// The Query
db.contents.find({
"_id" : ObjectId(1),
"shapes.color":"red"
},{
"_id": 0,
"shapes" :{
"$elemMatch":{
"color" : "red"
}
}
})
//And the Result
{"shapes":[
{
"shape" : "square",
"color" : "red"
}
]}
另一个有趣的方法是使用,这是MongoDB 2.6的新聚合特性之一。如果您使用的是2.6,则不需要$unwind,如果您使用的是大型阵列,则可能会导致性能问题
db.test.aggregate([
{ $match: {
shapes: { $elemMatch: {color: "red"} }
}},
{ $redact : {
$cond: {
if: { $or : [{ $eq: ["$color","red"] }, { $not : "$color" }]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}}]);
$redact
“根据文档本身存储的信息限制文档内容”。因此,它将只在文档内部运行。它基本上是从上到下扫描文档,并检查它是否与处于$cond
状态的匹配,如果匹配,它将保留内容($$down
)或删除($$PRUNE
)
在上面的示例中,first$match
返回整个形状
数组,并且$redact将其剥离为预期结果
请注意,{$not:“$color”}
是必需的,因为它也会扫描顶部文档,如果$redact
在顶层找不到color
字段,则会返回false
,这可能会删除我们不想要的整个文档 更好您可以使用$slice
在匹配数组元素中查询返回数组中的重要对象是否有帮助
db.test.find({"shapes.color" : "blue"}, {"shapes.$" : 1})
$slice
在您知道元素的索引时很有用,但有时您需要
无论哪个数组元素符合您的条件。您可以返回匹配的元素
使用$
操作符。只需运行查询
db.test.find(
{"shapes.color": "red"},
{shapes: {$elemMatch: {color: "red"}}});
此查询的输出为
{
"_id" : ObjectId("562e7c594c12942f08fe4192"),
"shapes" : [
{"shape" : "circle", "color" : "red"}
]
}
正如您所期望的,它将给出与颜色匹配的数组中的确切字段:'red'
db.getCollection('aj').find({"shapes.color":"red"},{"shapes.$":1})
输出
使用聚合函数和$project
获取文档中的特定对象字段
db.getCollection('geolocations').aggregate([ { $project : { geolocation : 1} } ])
结果:
{
"_id" : ObjectId("5e3ee15968879c0d5942464b"),
"geolocation" : [
{
"_id" : ObjectId("5e3ee3ee68879c0d5942465e"),
"latitude" : 12.9718313,
"longitude" : 77.593551,
"country" : "India",
"city" : "Chennai",
"zipcode" : "560001",
"streetName" : "Sidney Road",
"countryCode" : "in",
"ip" : "116.75.115.248",
"date" : ISODate("2020-02-08T16:38:06.584Z")
}
]
}
同样,您可以找到多个
db.getCollection('localData').aggregate([
// Get just the docs that contain a shapes element where color is 'red'
{$match: {'shapes.color': {$in : ['red','yellow'] } }},
{$project: {
shapes: {$filter: {
input: '$shapes',
as: 'shape',
cond: {$in: ['$$shape.color', ['red', 'yellow']]}
}}
}}
])
虽然这个问题是9.6年前提出来的,但这对很多人都有很大的帮助,我就是其中之一。感谢大家提出的所有问题、提示和建议
db.getCollection('geolocations').aggregate([ { $project : { geolocation : 1} } ])
{
"_id" : ObjectId("5e3ee15968879c0d5942464b"),
"geolocation" : [
{
"_id" : ObjectId("5e3ee3ee68879c0d5942465e"),
"latitude" : 12.9718313,
"longitude" : 77.593551,
"country" : "India",
"city" : "Chennai",
"zipcode" : "560001",
"streetName" : "Sidney Road",
"countryCode" : "in",
"ip" : "116.75.115.248",
"date" : ISODate("2020-02-08T16:38:06.584Z")
}
]
}
db.getCollection('localData').aggregate([
// Get just the docs that contain a shapes element where color is 'red'
{$match: {'shapes.color': {$in : ['red','yellow'] } }},
{$project: {
shapes: {$filter: {
input: '$shapes',
as: 'shape',
cond: {$in: ['$$shape.color', ['red', 'yellow']]}
}}
}}
])
db.employees.find( {"leave_history.calendar_year": 2020},
{leave_history: {$elemMatch: {calendar_year: 2020}},empno:true,ename:true}).pretty()
{
"_id" : ObjectId("5e907ad23997181dde06e8fc"),
"empno" : 7839,
"ename" : "KING",
"mgrno" : 0,
"hiredate" : "1990-05-09",
"sal" : 100000,
"deptno" : {
"_id" : ObjectId("5e9065f53997181dde06e8f8")
},
"username" : "none",
"password" : "none",
"is_admin" : "N",
"is_approver" : "Y",
"is_manager" : "Y",
"user_role" : "AP",
"admin_approval_received" : "Y",
"active" : "Y",
"created_date" : "2020-04-10",
"updated_date" : "2020-04-10",
"application_usage_log" : [
{
"logged_in_as" : "AP",
"log_in_date" : "2020-04-10"
},
{
"logged_in_as" : "EM",
"log_in_date" : ISODate("2020-04-16T07:28:11.959Z")
}
],
"leave_history" : [
{
"calendar_year" : 2020,
"pl_used" : 0,
"cl_used" : 0,
"sl_used" : 0
},
{
"calendar_year" : 2021,
"pl_used" : 0,
"cl_used" : 0,
"sl_used" : 0
}
]
}