在MongoDB中选择嵌套字段

11

我在mongodb中有一个集合,其中字段嵌套在语言根下:

{
    en: {
        title: "eng title",
        content: "eng content",
    },
    it: {
        title: "it title",
        content: "it content"
    }
    //common attributes for all languages
    images: {
        mainImage: "dataURL",
        thumbImage: "dataURL"
    }
}

我有一个名为'currentLang'的变量;我需要通过标题查找文档,仅选择"currentLang"对象和常见字段(例如此示例中的图像); 但对于"currentLang"对象,我希望输出的文档不是嵌套的;例如,当currentLang = "en"时。

期望输出:

{
    title: "eng title",
    content: "eng content",
    images: {
        mainImage: "dataURL",
        thumbImage: "dataURL"
    }
}

这是可能的吗?

2个回答

7

您需要按以下方式聚合:

  • 构建一个find对象,仅匹配包含语言($exists)的记录。
  • 构建一个Projection对象以投射字段。

代码:

var currentLang = "en";
var project = {};
project["title"] = "$"+currentLang+".title";
project["content"] = "$"+currentLang+".content";
project["images"] = 1;

var find = {};
find[currentLang] = {"$exists":true};

db.collection.aggregate([
{$match:find},
{$project:project}
])

这正是我现在正在使用的代码;但输出文档仍然嵌套在“en”下面;我希望所有字段都在根元素中,就像上面所写的期望输出一样。 - Cereal Killer
@CerealKiller 然后您需要聚合,投影一个带有别名的字段。请参见更新的答案。 - BatScream
好的,这是正确的;不幸的是,我正在Meteor.js中使用mongo,聚合似乎不受支持;抱歉,在我写问题时我并不知道... - Cereal Killer
@CerealKiller 没问题。- 看看这个链接是否有帮助 https://dev59.com/cWMl5IYBdhLWcg3wTlYl 。或者您可以发布一个新的问题,询问如何在meteor中完成此操作。 - BatScream
虽然不是非常重要,但为了遵循标准 - 由于前三个对象键是静态和已知的,您可能希望使用 project.title = 而不是 project["title"] =(您可以使用点符号表示法即时创建对象内的新字段 - 只要它不是嵌套未定义即可)。 - dylanh724

4
我不确定您是如何查询的,所以我假设您直接通过Mongo客户端进行查询。假设您已经定义了一个变量。
>currentLang = "en";

你可以运行一个聚合操作,并使用$project运算符,重新构建文档的呈现方式。
这里是我测试过的一个例子:
> db.test.aggregate({$project: 
        {_id: 0, 
         title: "$" + currentLang + ".title", 
         content: "$" + currentLang + ".content", 
         images: 1
        }
    }).pretty();
{
    "images" : {
        "mainImage" : "dataURL",
        "thumbImage" : "dataURL"
    },
    "title" : "eng title",
    "content" : "eng content"
}

如果您想将此与实际查询结合使用,只需将其作为 $match operator 包含即可,例如:
> db.test.aggregate(
    {$match: 
        {"en.title": "eng title"}
    }, 
    {$project: 
        {_id: 0, 
         title: "$" + currentLang + ".title", 
         content: "$" + currentLang + ".content", 
         images: 1
        }
    }).pretty();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接