这是一个典型的文件
{
title : 'someTitle',
places : [{name : 'someName', location : 'someLocation'}, {name ...}]
}
我有以下查询
var qs = {title : 'someTitle', places : {$elemMatch : {name : 'someName' } } };
我选择一个与标题相匹配的文档,其中包含一个文档条目,其中包含一个文档条目。名称等于' someName'的数组。但问题是places数组中的条目是大文档,我只需要该文档中的几个字段。我尝试像这样投射字段,但它没有用。
var projection = {'places.$.name': 1, 'places.$.location' : 1};
应该返回一个包含仅包含'name'
和'location'
属性的文档的数组。
我收到以下错误
Can't canonicalize query: BadValue Cannot specify more than one positional proj. per query.
要明确,我想在没有聚合框架的情况下实现这个目标
答案 0 :(得分:10)
你做错了。根据{{3}}
投影文档中只能出现一个位置
$
运算符。
但您仍然需要使用documentation运算符来获得预期结果:
var qs = { title : 'someTitle', 'places.name' : 'someName' };
var projection = {'places.$': 1 };
db.collection.find(qs, projection);
返回:
{
"_id" : ObjectId("564f52d7d9a433df958b5630"),
"places" : [
{
"name" : "someName",
"location" : "someLocation"
}
]
}
此外,您不需要$elemMatch
运营商使用$
代替。
现在,如果你想要的是一个" name"和"位置"对于数组中的每个子文档,聚合是可行的方法。
db.collection.aggregate([
{ '$match': {
'title' : 'someTitle',
'places.name' : 'someName'
}},
{ '$project': {
'places': {
'$map': {
'input': '$places',
'as': 'place',
'in': {
'name': '$$place.name',
'location': '$$place.location'
}
}
}
}}
])
哪个收益率:
{
"_id" : ObjectId("564f52d7d9a433df958b5630"),
"places" : [
{
"name" : "someName",
"location" : "someLocation"
},
{
"name" : "bar",
"location" : "foo"
}
]
}
答案 1 :(得分:1)
对于数组中的字段,您可以像在嵌入式对象中一样投影它们
var projection = {'places.name': 1, 'places.location' : 1};
查看此指南
https://docs.mongodb.com/manual/reference/operator/aggregation/project/#include-specific-fields-from-embedded-documents