如何从数组内的文档中投影特定字段?

nau*_*boy 10 mongoose mongodb mongodb-query aggregation-framework

这是一个典型的文件

{
   title : 'someTitle',
   places : [{name : 'someName', location : 'someLocation'}, {name ...}]
}
Run Code Online (Sandbox Code Playgroud)

我有以下查询

var qs = {title : 'someTitle', places : {$elemMatch : {name : 'someName' } } };
Run Code Online (Sandbox Code Playgroud)

我选择一个与标题匹配的文档,其中包含名称等于'someName'的'places'数组中的文档条目.但问题是places数组中的条目是大文档,我只需要该文档中的几个字段.我尝试像这样投射字段,但它没有用.

var projection = {'places.$.name': 1, 'places.$.location' : 1};
Run Code Online (Sandbox Code Playgroud)

应该返回一个包含仅包含'name''location'属性的文档的数组.

我收到以下错误

Can't canonicalize query: BadValue Cannot specify more than one positional proj. per query.  
Run Code Online (Sandbox Code Playgroud)

要清楚,我想在没有聚合框架的情况下实现这一目标

sty*_*ane 14

你做错了.根据文件

$投影文档中只能出现一个位置运算符.

但是您仍然需要使用$运算符来获得预期的结果:

var qs = { title : 'someTitle', 'places.name' : 'someName' };
var projection = {'places.$': 1 };
db.collection.find(qs, projection);
Run Code Online (Sandbox Code Playgroud)

哪个回报:

{
        "_id" : ObjectId("564f52d7d9a433df958b5630"),
        "places" : [
                {
                        "name" : "someName",
                        "location" : "someLocation"
                }
        ]
}
Run Code Online (Sandbox Code Playgroud)

此外,您不需要$elemMatch操作员在此使用"点符号".


现在,如果你想要的是数组中每个子文档的"name"和"location"数组,那么聚合就是你要走的路.

db.collection.aggregate([
    { '$match': { 
        'title' : 'someTitle', 
        'places.name' : 'someName' 
    }}, 
    { '$project': { 
        'places': {
            '$map': { 
                'input': '$places', 
                'as': 'place', 
                'in': { 
                    'name': '$$place.name', 
                    'location': '$$place.location'
                }
            }
        }
    }}
])
Run Code Online (Sandbox Code Playgroud)

产量:

{
    "_id" : ObjectId("564f52d7d9a433df958b5630"),
    "places" : [
            {
                    "name" : "someName",
                    "location" : "someLocation"
            },
            {
                    "name" : "bar",
                    "location" : "foo"
            }
    ]
}
Run Code Online (Sandbox Code Playgroud)


Cao*_*ang 10

对于数组中的字段,您可以像嵌入对象中一样对它们进行投影
var projection = {'places.name': 1, 'places.location' : 1};
检查此指南
https://docs.mongodb.com/manual/reference/operator/aggregation/project/#include-specific-fields-from-embedded -文件