【问题标题】:Meteor : Update an element in a specified array index in MongoDBMeteor:更新 MongoDB 中指定数组索引中的元素
【发布时间】:2018-09-21 02:04:22
【问题描述】:

所以我来自纯 javascript 背景,我正在从事一个流星项目,在该项目上我有以下名为“Semaines”的 MongoDB 集合:

{
    _id: /*random ID*/,
    id_utilisateur: /*user ID*/,
    isCreated: true,
    jours: {
        lundi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        mardi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        mercredi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        jeudi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        vendredi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        samedi: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        dimanche: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    }
}

使用下面的方法,我想在指定的日期和索引(这里代表小时)更新元素:

    //sent values are : idUt = Meteor.userId(), day = "vendredi", hour = 0, score = 10
    'semaines.updateTable'(idUt, day, hour, score){
        check(idUt, String);
        check(day, String);
        check(hour, Number);
        check(score, Number);
        Semaines.update({id_utilisateur: idUt},{$set : {"jours.$[day].$[hour]": score}});
    }

这似乎不起作用。我认为这是因为查询实际上是我发送的值:

    $set : {jours.vendredi.0 : 10}

这显然行不通,但我看不到我的查询如何变成这样,我认为它会起作用:

    $set : {jours.vendredi[0] : 10}

【问题讨论】:

  • 能否请您添加要更新的文档的当前完整结构?

标签: javascript arrays mongodb meteor


【解决方案1】:

Meteor > 1.6.2 / Mongo > 3.6 的解决方案 - 使用 arrayFilter:

您要做的是在查询中使用computed properties ({[keyVar]: val}),然后嵌套它。

您还需要使用arrayFilter 来定位数组的特定索引

Semaines.update(
  { id_utilisateur: idUt },
  { $set : { jours: { [day]: { "$[index]": score } } } },
  { arrayFilters: [ { index: hour } ] },
);

因为目前是这个文字串:"jours.$[day].$[hour]"

我不确定 Meteor Collections 是否通过这样的选项,因此您可能需要获取原始 mongo 集合:

Semaines.rawCollection().update(
  { id_utilisateur: idUt },
  { $set : { jours: { [day]: { "$[index]": score } } } },
  { arrayFilters: [ { index: hour } ] },
);

Meteor

由于无法访问 Mongo 3.6 中更强大的运算符,我们只能自己在 javascript 中完成工作:

'semaines.updateTable'(idUt, day, hour, score){
    check(idUt, String);
    check(day, String);
    check(hour, Number);
    check(score, Number);
    const doc = Semaines.findOne({ id_utilisateur: idUt });
    const array = doc.jours[day];
    array[hour] = score;
    Semaines.update(
        { id_utilisateur: idUt },
        // Replace the entire jours object with a clone and modify day
        { $set : { jours: { ...doc.jours, [day]: array } } },
    );
}

注意:虽然 Mongo 3.4 为 $push 提供了一个 $position 选项,但它没有为 $pull 提供该选项,因此我们不能就地替换元素

【讨论】:

  • 我不知道是否需要对您的代码进行任何修改,但直接复制/粘贴会返回此错误。 “模拟调用 'semaines.updateTable' 的效果时出现异常 errorClass {isClientSafe: true, error: 409, reason: "MinimongoError: Key $[index] must not start with '$'", details: undefined, message: "MinimongoError : Key $[index] must not start with '$' [409]", ...} Error: MinimongoError: Key $[index] must not start with '$' [409]"
  • 我会启动一个流星应用来看看
  • 我错过了文档中提到 "$[foo]": 语法是 3.6 版中的新语法的部分。直到 Meteor 1.6.2 才会出现
  • 编辑答案以包含当前 Meteor+Mongo 版本的解决方案
  • 它几乎可以完美运行:现在它删除了其他“lundi”、“mardi”等数组,但我发现的一个修复方法是简单地删除包含七个数组的“jours”对象。现在可以了,谢谢!知道为什么它会这样吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-09
  • 2017-07-02
  • 1970-01-01
  • 2012-07-07
  • 2012-03-04
相关资源
最近更新 更多