当前位置: 首页 > 知识库问答 >
问题:

查询MongoDB数组中的数组;如果存在则更新,如果为空则插入

邢凌
2023-03-14

我想修改MongoDB中的文档。以下是相关文档结构的示例摘录:

{ values : { M1 : [[1395964800, 0.083434], ... , [1395964860, 0.043424]] } }

首先,keyM1包含一个数组数组。我必须搜索嵌套数组中的[0]项(纪元时间,例如1395964800,1395964860)。如何通过[0]嵌套数组值查找文档?例如,我尝试搜索:

db.myCollection.find({ "values" : { "M1" : [1395964800, 0.083434] } }).limit(1);

诚然,我预计这种方法将通过[0]嵌套数组值进行搜索

其次,如果这个[0]数组值已经存在(纪元时间),我想更新/覆盖嵌套数组中的[1]元素(数据值)。如果[0]数组值在M1数组中不存在,我想将其(以及随附的数据值)添加到M1数组中。

我希望我会使用类似的东西:

db.collection("myCollection").findAndModify(
   { ........ }, // query
   { }, // sort
   { $set : { ... : ... }}, // set
   { upsert: true }, // insert if does not exist
   function (err, result) {
      (err) throw err
   }
);

问题

  1. 如何按说明进行搜索
  2. 如何按说明更新

共有2个答案

宗政霄
2023-03-14

这里有匿名嵌套数组,这不是在MongoDB中处理数据的好格式。除了选择问题之外,匹配要更新的项目是一个真正的问题,因为只有在尝试实际匹配位置时,您才仅限于第一个索引匹配*。

请参见位置$运算符留档。

要解决这个问题,您实际上需要一个适合的模式,例如:

{ 
    values : { 
        M1 : [
            { "time": 1395964800, "value": 0.083434 },
            { "time": 1395964860, "value": 0.043424 } 
        ]
    }
}

使用该结构,您可以搜索“时间”值,如下所示:

db.collection.find(
    { "values.M1.time": 1395964860 },
    { "values.M1.$": 1 }
)

这将把数组的“匹配”元素投影到文档中找到它的地方。

对于更新,您可以使用相同的位置运算符:

db.collection.update(
   { "values.M1.time": 1395964860 },
   { "$set": { "values.M1.$.value": 0.055000 } }
)

但是对于当前的嵌套形式,您不能比显式匹配更好:

db.collection.find({ "values.M1.0.0": 1395964800 })

您需要知道要匹配的内容的索引值,这违背了存储它的目的。

更改您的架构,这将是一个更加灵活的解决方案。

冯驰
2023-03-14

下面的代码是我为解决我的问题而创建的解决方案。特别是,以下线索帮助了我:

  • MongoDB 嵌套数组查询
  • 对嵌套数组元素的 Mongodb 查询

需要明确的是,在我的情况下,unixTime值在数组本身和嵌套数组之间都是唯一的。我希望其他人觉得这有帮助。

var unixTime = 1395964800; // e.g. This can be programmatically changed
var _query = {'values.M1' : { '$elemMatch' : { '$in' : [unixTime] } } } ; // This allows us to search within the nested arrays for a specific value (in any position).

db.collection("myCollection").findAndModify(
    _query, // query
    { start_timestamp : -1 }, // sort
    { $set : { 'values.M1.$' : [unixTime, value] }}, // set with $, which is crucual because it uses the previously found/matched array item
    { upsert: true}, // insert if does not exist
    function (err, result) {
        if (err) console.log(error);
        console.log('results',results);
    }
);
 类似资料:
  • 问题内容: 我有一个带有2个表的数据库,如下所示: 列是,并且是 和 在申请表中,我有2个编辑框,名称分别为和 如果用户像电子邮件一样插入一个新的负责人姓名, 那么在保存表格的过程中,我想将新的负责人姓名插入表中,请插入最后一个并将其更新为。 如果用户保持名称,但它更新电子邮件一样,然后我想在从1 =使用新的电子邮件地址和他们(其余和)保持不变。 如果负责人的名称相同,我想保留from表的原始引用

  • 问题内容: 我有这样的简单表: 我想更新哪里的行,但是如果没有行我想更新的行: 仅可能进行一次查询吗? 问题答案: 你可以利用 列上应该有UNIQUE索引 SQLFiddle

  • 问题内容: 我希望使用以下update \ insert方法来加快我的应用程序insert \ updates的速度: 我将如何使用sql参数来做到这一点?由于@@,将把rowcount函数作为参数。 http://blogs.msdn.com/b/miah/archive/2008/02/17/sql-if-exists-update-else- insert.aspx 问题答案: 这种模式称为

  • 问题内容: 如果给定的文件名已经在数据库中,我想在表中进行更新,否则我想插入新行。我尝试此代码,但显示的错误请给我正确的方式,因为我在SQL中更新鲜 问题答案: 你应该 在查询中使用 参数 - 总是! - 没有例外 创建一个处理 服务器上零件的单个查询 __ 使用公认的ADO.NET最佳实践将事物放入块等。 试试下面的代码:

  • 问题内容: 我有一些看起来像这样的代码。我必须保留表中的一个自动递增字段(在其他表中使用)。我想简化和优化此代码。 编辑:主键ID是自动递增的字段。我永远都不想改变。但是,当另一个字段重复时,这就是我要更新该记录的时间。 问题答案: 如何替换成: 假设col1是您的主键,如果已经存在一个值为’foo’的行,它将更新其他两列。否则,它将插入新行。

  • 问题内容: 再会。我有3张桌子: tblWarehouse产品 : tblBranchProducts : tblStockMoves : 基本上,该过程是分支X从仓库Y请求产品。然后仓库Y创建一个请求订单(称为“ 库存移动” )并将请求存储在 tblStockMove中 。 说这种情况,我们有一个参考编号为XYZ的库存移动: (其中产品ID 1为可乐,产品ID 2为百事可乐。) 另一方面,分支X