将数组索引匹配到提供的对象variables

我有这样的外部对象:

var obj = { a: 2, b: 0, c: 1 } 

此外,我有与引用obj字段“ref”的集合。 obj对象中的值被视为集合中的数组字段的索引。

 { ref: "a", array: ["xyz", "abc", "def"] } { ref: "b", array: ["sde", "xda", "era"] } { ref: "c", array: ["wwe", "aea", "fre"] } 

我想聚集收集只有一个取决于在obj中指定的索引值的数组。

 .aggregate([ { $project: { code: $arrayElemAt: ["$array", { $let: { vars: { obj: obj }, in: "$$obj.$ref" //Field path used as variable field name of object }}] } }]) 

但是我得到以下错误:

 MongoError: FieldPath field names may not start with '$'. 

这是相关的我认为以下的东西: in: "$$obj.$ref"

所需的聚合结果是:

 { ref: "a", code: "def" } { ref: "b", code: "sde" } { ref: "c", code: "aea" } 

你有点走错了路,但是你在错误的地方使用$let 。 所以总的想法是应用$let “围绕”expression式来评估,而不是“内部”。

另外,你真的应该把这个对象作为一个input值与一个“数组”进行匹配。 操作符使用“数组”,而不处理通过variables名称很好地查找“对象”。

所以这可能是最短的$indexOfArray$arrayElemAt ,两者都可用来匹配和提取值:

 var obj = { a: 2, b: 0, c: 1 }; var input = Object.keys(obj).map(k => ({ k: k, v: obj[k] })); // Outputs as // [{ "k" : "a", "v" : 2 }, { "k" : "b", "v" : 0 }, { "k" : "c", "v" : 1 }] db.collection.aggregate([ { "$addFields": { "array": { "$let": { "vars": { "obj": input }, "in": { "$arrayElemAt": [ "$array", { "$arrayElemAt": [ "$$obj.v", { "$indexOfArray": [ "$$obj.k", "$ref" ] } ]} ] } } } }} ]) 

如果你真的有MongoDB 3.4.4或更高版本,那么你可以“内部”应用$objectToArray ,但是它并没有真正添加任何值(它真的只是炫耀):

 var obj = { a: 2, b: 0, c: 1 }; //var input = Object.keys(obj).map(k => ({ k: k, v: obj[k] })); db.collection.aggregate([ { "$addFields": { "array": { "$let": { "vars": { "obj": { "$objectToArray": obj } }, "in": { "$arrayElemAt": [ "$array", { "$arrayElemAt": [ "$$obj.v", { "$indexOfArray": [ "$$obj.k", "$ref" ] } ]} ] } } } }} ]) 

如果您的MongoDB不支持$indexOfArray ,那么您总是可以应用$map$filter来获取这些合并语句中的“first match”: $arrayElemAt

 var obj = { a: 2, b: 0, c: 1 }; var input = Object.keys(obj).map(k => ({ k: k, v: obj[k] })); db.collection.aggregate([ { "$addFields": { "array": { "$arrayElemAt": [ "$array", { "$arrayElemAt": [ { "$map": { "input": { "$filter": { "input": input, "cond": { "$eq": [ "$$this.k", "$ref" ] } } }, "in": "$$this.v" }}, 0 ]} ] } }} ]) 

这也消除了$let任何用法,因为我们不直接针对提供给variables的"input"$filter以外的任何东西。

无论哪个应用,都来自相同的输出使用从inputobj提供的索引位置(强制input为数组),并返回该数组条目:

 /* 1 */ { "_id" : ObjectId("59a76d6fad465e105d9136dc"), "ref" : "a", "array" : "def" } /* 2 */ { "_id" : ObjectId("59a76d6fad465e105d9136dd"), "ref" : "b", "array" : "sde" } /* 3 */ { "_id" : ObjectId("59a76d6fad465e105d9136de"), "ref" : "c", "array" : "aea" }