【问题标题】:Upsert with $exists not allowed: The dollar ($) prefixed field is not valid for storageUpsert with $exists not allowed: 美元 ($) 前缀字段对存储无效
【发布时间】:2017-12-13 13:57:10
【问题描述】:

此 Meteor 服务器端 (Mongo 1.1.18) 尝试根据所示选择器更新插入文档,但出现以下错误:

  myCol.upsert({name: 'sam', job: {$exists: false}}, {$set: {parents: ['jack', 'jacky']}});

MongoError: 'job.$exists' 中的美元 ($) 前缀字段 '$exists' 对存储无效。

如何更新插入到这个选定的文档?或者如果它不存在就创建它?谢谢

【问题讨论】:

    标签: mongodb meteor mongodb-query


    【解决方案1】:

    原因是因为"upsert" MongoDB 试图在新创建的对象中分配作为“值”提供的任何“查询”参数。由于您无法使用 $ 命名属性,因此会引发错误,因为它正在尝试将字段“job”创建为 { "job": { "$exists": true } },就像您在查询参数中提供的一样。

    为避免这种情况,请通过指定 $setOnInsert 告诉 MongoDB 在创建时实际使用哪些字段。至少对于普通的 MongoDB 集合来说是这样。因此,对于“流星”,您应该访问 .rawCollection() 而不是“

    myCol.rawCollection().update(
      {name: 'sam', job: {$exists: false}},
      {
       $setOnInsert: { name: 'sam' },
       $set: {parents: ['jack', 'jacky']}
      },
      { upsert: true }
    )
    

    请注意,当您执行此操作时,不会使用其他各种流星默认值,例如 _id 的值,因此您可能需要使用替代方法。

    这里的替代方法是改用 $where,它可以根据文档评估 JavaScript 条件以查看 "job" 字段不存在。即使从流星收集实现中,这实际上也不会被转移到“upsert”:

    myCol.upsert(
      {name: 'sam', '$where': "!this.hasOwnProperty('job')" },
      {
       $set: {parents: ['jack', 'jacky']}
      }
    )
    

    为了证明这一点,我启动了一个纯流星项目,除了添加一个集合并在服务器启动时执行代码之外没有其他任何更改。所以基本上在一个新项目上更改server/main.js如下:

    import { Meteor } from 'meteor/meteor';
    import { People } from '../imports/people.js';
    
    Meteor.startup(() => {
      // code to run on server at startup
    
      People.upsert(
        { name: 'john', '$where': "!this.hasOwnProperty('job')" },
        {
          '$set': { parents: [ 'jack', 'jacky' ] }
        }
      );
    
      People.rawCollection().update(
        { name: 'bill', job: { '$exists': false }  },
        {
          '$setOnInsert': { name: 'bill' },
          '$set': { parents: [ 'jack', 'jacky' ] }
        },
        { 'upsert': true }
      )
    
    });
    

    还有imports/people.js

    import { Mongo } from 'meteor/mongo';
    
    export const People = new Mongo.Collection('people');
    

    并且文档按预期在集合中创建,没有错误:

    {
            "_id" : "irDWFLdACjNKYGEcN",
            "name" : "john",
            "parents" : [
                    "jack",
                    "jacky"
            ]
    }
    {
            "_id" : ObjectId("596489d0902edee769372ac6"),
            "name" : "bill",
            "parents" : [
                    "jack",
                    "jacky"
            ]
    }
    

    【讨论】:

    • 我尝试了您发布的第一个代码,但它给出的错误与我发布的相同。
    • @FredJ。抱歉,错过了您的留言。你是从 minimongo 还是后端尝试这个?您使用的是哪个版本的 MongoDB?在 3.4 后端对我来说效果很好。还有另一个使用$where 的选项,但$setOnInsert 应该可以工作。
    • 我正在使用运行 mongo1.1.18 的 Meteor,它是一个 javascript 框架,您提供的代码已按原样复制并粘贴到 javascript 代码中。
    • @FredJ。我知道什么是流星,实际上问你这是来自“minimongo”(即流星“浏览器端”界面)还是来自几乎直接使用核心驱动程序的后端。我还询问了“MongoDB 服务器”版本,而您似乎正在查看已实现的驱动程序,而且它似乎是一个旧的驱动程序。您可以尝试更新您的流星分布,因为 1.1.18 驱动程序会表明它已经很旧了。关键是这适用于我们其他人。就像我在这里展示的那样。
    • 正如问题“Meter 服务器端”的第一行所述,它不是浏览器 minimongo。所以在我的情况下它是后端:)。我的流星是最新的更新。至于MongoDB服务器,3.2.13,由第三方托管在云端。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    • 2019-12-27
    • 2023-03-27
    • 2020-05-24
    • 1970-01-01
    相关资源
    最近更新 更多