【问题标题】:Return only the queried element and its parent from a nested document从嵌套文档中只返回查询的元素及其父元素
【发布时间】:2014-09-25 17:43:58
【问题描述】:

我有以下架构结构

Artist Schema
albums:[Albums Schema]

Album Schema
songs:[Songs Schema]

现在,我想按歌曲 ID 搜索并返回歌曲、其父专辑和艺术家详细信息。我不想退回匹配的歌曲和专辑以外的歌曲和专辑。到目前为止,我只能将其限制为使用 positional 或 elemMatch 返回查询的专辑,但它仍然返回所有歌曲。有谁知道将歌曲和专辑元素限制为一个的方法?

【问题讨论】:

  • 似乎您不能对嵌套数组使用 $elemMatch 投影。顺便说一句,如果一张专辑有两位艺术家怎么办。这不是这个架构的问题吗?
  • 是的,这也是我发现的。我与聚合框架和编辑很接近,但它非常混乱。不,为了我的申请,一张专辑只能属于一位艺术家。

标签: node.js mongodb mongoose


【解决方案1】:

为方便起见,下面的示例使用mongo shell,但应该是 直接翻译。

假设您的架构类似于:

db.artist.insert({
    name: '"Weird Al" Yankovic',
    albums: [
        {
            name: 'Dare to Be Stupid',
            year: 1995,
            songs: [
                { track: 'A1', name: 'Like a Surgeon' },
                { track: 'A2', name: 'Dare to Be Stupid' },
                { track: 'A3', name: 'I Want a New Duck' },
            ],
        },
        {
            name: 'Polka Party!',
            year: 1985,
            songs: [
                { track: 'A1', name: 'Living with a Hernia' },
                { track: 'A2', name: 'Dog Eat Dog' },
                { track: 'A3', name: 'Addicted to Spuds' },
            ],
        },
    ],
})

您可以使用Aggregation Framework 来获得预期的结果:

db.artist.aggregate(

    // First match to reduce the number of candidate documents
    { $match: {
        "albums.songs.name": "I Want a New Duck",
    }},

    // Unwind 'albums' & 'songs' arrays
    { $unwind: "$albums" },
    { $unwind: "$albums.songs" },

    // Limit to matching song & album
    { $match: {
        "albums.songs.name": "I Want a New Duck",
    }}
)

示例结果:

{
    "_id" : ObjectId("53defb826ed136423e50d082"),
    "name" : "\"Weird Al\" Yankovic",
    "albums" : {
        "name" : "Dare to Be Stupid",
        "year" : 1995,
        "songs" : {
            "track" : "A3",
            "name" : "I Want a New Duck"
        }
    }
}

【讨论】:

  • 天哪,你真是个天才。我想我是个秃头,毕竟这里的头发拉着人。我从来不知道你可以使用 $match 两次。在 $unwind 之前使用 $match 很重要,因为否则 mongo 无法使用索引。高超。谢谢:
  • @KhalidBajwa 事实上,几乎所有的聚合管道运算符(除了$geoNear$out)都可以重复:)。正如您所提到的,初始$match 可以利用索引,并且还可以减少对管道中稍后不匹配的文档的不必要处理。仅供参考,MongoDB 手册有更多关于 pipeline optimization 的提示以及一些有趣的 Aggregation with the Zip Code Data Set 示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 2016-07-13
相关资源
最近更新 更多