如何从 MongoDB 数组中检索第一个和最后一个元素并将其设置为不同的字段?

Posted

技术标签:

【中文标题】如何从 MongoDB 数组中检索第一个和最后一个元素并将其设置为不同的字段?【英文标题】:How to retrieve first and last elements from MongoDB array and set it as distinct fields? 【发布时间】:2021-09-25 10:45:30 【问题描述】:

我的收藏:


        "_id" : ObjectId("60e46c1dfc320656ffc683b4"),
        "name" : "A",
        "name_test" : "a b c",
        "arr" : [
                "1",
                "2",
                "3"
        ]


        "_id" : ObjectId("60e46c20fc320656ffc683b5"),
        "name" : "B",
        "name_test" : "B A",
        "arr" : [
                "a",
                "b",
                "c"
        ]


        "_id" : ObjectId("60e46c26fc320656ffc683b6"),
        "name" : "T1",
        "number" : 1,
        "name_test" : "T1",
        "arr" : [
                "t1",
                "t2",
                "t3"
        ]

我想用数组“arr”的firstlast元素扩展字段,例如:


            "_id" : ObjectId("60e46c26fc320656ffc683b6"),
            "name" : "T1",
            "number" : 1,
            "name_test" : "T1",
            "arr" : [
                    "t1",
                    "t2",
                    "t3"
            ],
            "first": "t1",
            "last": "t3"
    

我正在为 Mongo 尝试这个命令:

db.test_coll.update(, 
        [ $set: 
               first:  $arrayElemAt: [ "$arr", 0 ], 
                last:  $arrayElemAt: [ "$arr", -1 ] 
              ,
        ])
                        

我也试过了:

db.test_dups.updateMany($where: "this.arr.length > 1", ...

但没有成功。我得到下一个错误:

[thread1] Error: the update operation document must contain atomic operators :
DBCollection.prototype.updateMany@src/mongo/shell/crud_api.js:568:1

我该怎么做?也许使用 PyMongo?


问题解决方案: 我的 mongo 是 3.2,大多数命令都不能在那里工作,所以我使用 PyMongo 解决了它:

bulk = db.test.initialize_ordered_bulk_op()

cnt = 0
for profiles in db.test.find():
    cnt += 1 
    
    try:
        bulk.find('_id': profiles['_id']).update('$set': 
                'f': profiles['arr'][0],
                'l': profiles['arr'][-1]
            
        )

        if cnt % 1000000 == 0:
            print("Exectuting", cnt)
            bulk.execute()
            bulk = db.test.initialize_ordered_bulk_op()
    except:
        print(profiles['_id'], " - Did not worked out")
    
try:
    bulk.execute()
except:
    print("Bulk is Empty")

【问题讨论】:

【参考方案1】:

问题解决方案: 我的 mongo 是 3.2,大多数命令都不能在那里工作,所以我使用 PyMongo 解决了它:

bulk = db.test.initialize_ordered_bulk_op()

cnt = 0
for profiles in db.test.find():
    cnt += 1 
    
    try:
        bulk.find('_id': profiles['_id']).update('$set': 
                'f': profiles['arr'][0],
                'l': profiles['arr'][-1]
            
        )

        if cnt % 1000000 == 0:
            print("Exectuting", cnt)
            bulk.execute()
            bulk = db.test.initialize_ordered_bulk_op()
    except:
        print(profiles['_id'], " - Did not worked out")
    
try:
    bulk.execute()
except:
    print("Bulk is Empty")

【讨论】:

【参考方案2】: $expr$gt 检查arr 长度应该大于1 $first$last 运算符从 arr 中选择元素
db.test_dups.updateMany(
   $expr:  $gt: ["$arr", 1]  ,
  [
    $set: 
      first:  $first: "$arr" ,
      last:  $last: "$arr" 
    
  ]
)

Playground

【讨论】:

你的逻辑绝对正确,但我还是得到:错误:更新操作文档必须包含原子操作符 1) 你在哪里执行这个查询? 2)你的mongodb服务器的版本是什么?这将从 mongodb v4.2 开始工作。 该死,我很抱歉,我使用的是带有 mongo 3.2 的服务器 .... 这就是整个问题,我在 PyMongo 中解决了它,我会在一分钟内编辑我的答案 无论如何谢谢!!!

以上是关于如何从 MongoDB 数组中检索第一个和最后一个元素并将其设置为不同的字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python脚本从mongoDB中检索数组中的子文档

返回一个在 mongoDB 中有一个数组的字段,并返回该数组中的第一个和最后一个值

从3个表中检索数据如何使用Laravel中的第一个表从最后一个表中检索数据

如何从表中检索我的最后一个插入行?

使用 swift 将数组保存和检索到用户默认值

从 GoLang 中的 mongodb 获取最后插入的元素