我正在使用mongoose.js对mongodb进行查询,但我认为我的问题不是mongoose.js特有的.
假设我在集合中只有一条记录:
var album = new Album({
tracks: [{
title: 'track0',
language: 'en',
},{
title: 'track1',
language: 'en',
},{
title: 'track2',
language: 'es',
}]
})
Run Code Online (Sandbox Code Playgroud)
我想选择语言字段等于'en'的所有曲目,所以我尝试了两种变体:
Album.find({'tracks.language':'en'}, {'tracks.$': 1}, function(err, albums){
Run Code Online (Sandbox Code Playgroud)
和$ elemMatch投影绑定到同一个东西:
Album.find({}, {tracks: {$elemMatch: {'language': 'en'}}}, function(err, albums){
Run Code Online (Sandbox Code Playgroud)
无论哪种情况,我都得到了相同的结果:
{tracks:[{title: 'track0', language: 'en'}]}
Run Code Online (Sandbox Code Playgroud)
selected album.tracks只包含一个标题为'track0'的轨道元素(但应该同时包含'track0','track1'):
{tracks:[{title: 'track0', language: 'en'}, {title: 'track1', language: 'en'}]}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
mne*_*syn 12
就像@JohnnyHK已经说了,你就必须使用聚合框架来实现这一目标,因为两者$并$elemMatch只返回第一个匹配.
这是如何做:
db.Album.aggregate(
// This is optional. It might make your query faster if you have
// many albums that don't have any English tracks. Take a larger
// collection and measure the difference. YMMV.
{ $match: {tracks: {$elemMatch: {'language': 'en'}} } },
// This will create an 'intermediate' document for each track
{ $unwind : "$tracks" },
// Now filter out the documents that don't contain an English track
// Note: at this point, documents' 'tracks' element is not an array
{ $match: { "tracks.language" : "en" } },
// Re-group so the output documents have the same structure, ie.
// make tracks a subdocument / array again
{ $group : { _id : "$_id", tracks : { $addToSet : "$tracks" } }}
);
Run Code Online (Sandbox Code Playgroud)
您可能希望仅使用第一个表达式尝试该聚合查询,然后逐行添加表达式以查看输出的更改方式.了解如何$unwind创建稍后使用$group和重新合并的中间文档尤为重要$addToSet.
结果:
> db.Album.aggregate(
{ $match: {tracks: {$elemMatch: {'language': 'en'}} } },
{ $unwind : "$tracks" },
{ $match: { "tracks.language" : "en" } },
{ $group : { _id : "$_id", tracks : { $addToSet : "$tracks" } }} );
{
"result" : [
{
"_id" : ObjectId("514217b1c99766f4d210c20b"),
"tracks" : [
{
"title" : "track1",
"language" : "en"
},
{
"title" : "track0",
"language" : "en"
}
]
}
],
"ok" : 1
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5833 次 |
| 最近记录: |