gpt4 book ai didi

node.js - 将数组索引与提供的对象变量相匹配

转载 作者:太空宇宙 更新时间:2023-11-04 00:17:53 24 4
gpt4 key购买 nike

我有这样的外部对象:

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 “围绕”要计算的表达式,而不是“内部”。

此外,在作为输入值馈送到管道之前,您确实应该使对象与“数组”匹配。这些运算符使用“数组”,但不能很好地处理通过变量名称查找“对象”。

因此,使用 $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相反,它并没有真正增加任何值(value)(它只是真正地炫耀):

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$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 的任何使用因为除了 $filter"input" 之外,我们不会针对所提供的任何变量进行注释。直接。

无论应用哪一种,都会得到相同的输出,该输出使用输入 obj 中提供的索引位置(强制为 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"
}

关于node.js - 将数组索引与提供的对象变量相匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45970421/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com