【问题标题】:MongoDB Double Upsert and a PushMongoDB Double Upsert 和推送
【发布时间】:2015-05-18 21:00:45
【问题描述】:

我在 Mongo 中有以下数据结构:

{
  "_id": "L7ucxMsTSfTDtctnt",
  "lectures": [
    {
      "_id": "Tfr3DMxavZwP5yy6F",
      "notes": [
        {
          "slide": 1,
          "notes": "First Note",
          "timestamp": "2015-05-18T20:18:36.510Z"
        },
        {
          "slide": 2,
          "notes": "Another note",
          "timestamp": "2015-05-18T20:18:36.510Z"
        }
      ]
    }
  ]
}

我正在尝试进行三重插入和数组推送。因此,如果外部 _id 不存在,则创建它,否则更新它。如果 Lecture _id 不存在,则创建它,否则更新它。如果 notes _id 不存在,则创建对象并推送到 notes 数组,否则更新它。

有可能做这么复杂的事情吗?我可以分三个单独的步骤来完成,但是我经常调用该函数并且担心性能。

【问题讨论】:

  • notes id 是什么?

标签: javascript mongodb meteor mongodb-query


【解决方案1】:

如果您可以分 3 步完成此操作,那将是非常令人印象深刻的......哎呀,只是试图编写一个查询以返回具有该模式的单个注释对象,这让我的大脑很痛苦。 (试试吧,你不会喜欢的)。

在第二层之后,对象模式的数组在 mongo 中开始变得非常麻烦。通常最好使用新集合或将其存储为子文档 (doc.lectures['alsfjljfldjf5084534']),因为这样您就有了要引用的内存地址,而不是试图执行嵌套的 $elemmatch

无论如何,要回答您的问题,只需 1 个 upsert,因为它只有 1 个文档。当您考虑整个事情是 1 文档时,您会更容易理解。只需获取文档并将其保存为 JS 对象即可。修改对象然后插入整个东西。不要担心传输几个额外字节的重复数据。用疯狂的迭代查询困扰您的数据库以找到您要编辑的文档中的特定点是 waaaaaayyyy 更费力。

在这种特殊情况下,您已经正确建模了 ER(1 个课程有很多讲座,1 个讲座有很多笔记)但是,根据您的查询模式,您可能希望将课程放在他们自己的集合中并包含classID 作为您的讲座集合中的 FK。然后,可以选择制作注释子文档以便于访问。

这样做,获取一个便笺对象就像这样简单: Lectures.findOne({notesID: '234asfj'})。当然,你会失去原子性,但这是一个很小的代价。

编辑:

doc = {}; //empty object
subDocId = Random.id(); //ref for subdoc
doc[subDocId] = {
    notes: 1,
    text: 'foo'
}; // create subdoc
Lecture.insert(doc); //insert subdoc

var doc = Lectures.findOne(); //get it
doc["Tfr3DMxavZwP5yy6F"] = {foo:1, bar:2} //mod it
Lecture.insert(doc); //upload it

【讨论】:

  • 感谢您的详细回复。我想我已经读了大约十遍了,我终于把头绕了过去。您能否提供一个示例,说明我将如何使用子文档(包括插入、更新和查找/检索)而不是使用对象数组?我了解使用内存引用的好处,但不知道如何实现它
  • 或者,如果你建议只获取对象,修改它,然后插入它,你能提供一个例子吗?
  • 使用第二个示例我得到: MongoError: insertDocument :: 由 :: 11000 E11000 重复键错误索引:meteor.notes.$_id_ dup key
猜你喜欢
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2015-11-30
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 2013-05-04
相关资源
最近更新 更多