Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 计算原子FindModify操作中的最大值_Mongodb - Fatal编程技术网

Mongodb 计算原子FindModify操作中的最大值

Mongodb 计算原子FindModify操作中的最大值,mongodb,Mongodb,我试图弄清楚在MongoDB中是否有可能推送一个元素,同时(原子find和modify操作)更新数组中元素的最大值 例如: { "_id": "...", "max_value": 10, "values": [2, 10, 6] } 在我插入20之后,结果将是: { "_id": "...", "max_value": 20, "values": [2, 10, 6, 20] } 将值20推送到值数组,并在相同的原子操作中重新计算最大值字段(为20) 有可能吗?编辑

我试图弄清楚在MongoDB中是否有可能推送一个元素,同时(原子
find和modify
操作)更新数组中元素的最大值

例如:

{
  "_id": "...",
  "max_value": 10,
  "values": [2, 10, 6]
}
在我插入20之后,结果将是:

{
  "_id": "...",
  "max_value": 20,
  "values": [2, 10, 6, 20]
}
将值20推送到值数组,并在相同的原子操作中重新计算最大值字段(为20)


有可能吗?

编辑:经过进一步思考,我原来的答案是正确的,但很浪费。具体来说,第一步是不必要的,因此这里有一个修订版本:

您可以通过两个步骤模拟此过程:

  • 使用当前尝试插入的值查找并修改
    \u id
    最大值
    $lte
    。由于
    \u id
    是唯一的,因此您知道只有零个或一个文档可以匹配此查询——假设存在具有该
    \u id
    的文档,如果
    最大值
    大于您插入的值,则为零,如果该值小于或等于,则为一。在更新中,
    $push
    新值,以及
    $set
    最大值

  • 如果且仅当步骤1失败时,使用
    \u id
    查找并再次修改,并
    $push
    将新值推送到数组中。由于步骤#1失败,我们知道当前的
    max_值
    大于新值,因此我们可以忽略它,只需
    $push
    新值

  • 下面是实现此功能的示例Python代码:

    # the_id is the ObjectId of the document we want to modify
    # new_value is the new value to append to the list
    rslt1 = rslt2 = None
    
    rslt1 = db.collection.find_and_modify(
        {'_id': the_id, 'max_value': {'$lte': new_value}},
        {'$push': {'array': new_value}, '$set': {'max_value': new_value}})
    
    if rslt1 is None:
        rslt2 = db.collection.find_and_modify(
            {'_id': the_id},
            {'$push': {'array': new_value}})
    
    # only one of these will be non-None; this
    # picks whichever is non-None and assigns
    # it to rslt
    rslt = rslt1 or rslt2
    
    # the_id is the ObjectId of the document we want to modify
    # new_value is the new value to append to the list
    rslt1 = rslt2 = rslt3 = None
    rslt1 = db.collection.find_and_modify(
        {'_id': the_id, 'max_value': {'$gt': new_value}},
        {'$push': {'array': new_value}})
    
    if rslt1 is None:
        rslt2 = db.collection.find_and_modify(
            {'_id': the_id, 'max_value': {'$lte': new_value}},
            {'$push': {'array': new_value}, '$set': {'max_value': new_value}})
    
    if rslt1 is None and rslt2 is None:
        rslt3 = db.collection.find_and_modify(
            {'_id': the_id},
            {'$push': {'array': new_value}})
    
    # only one of these will be non-None; this
    # picks whichever is non-None and assigns
    # it to rslt
    rslt = rslt1 or rslt2 or rslt3
    

    (这个原始答案有效,但上面的更新版本更有效。)

    您可以通过三个步骤模拟此过程:

  • 查找并修改具有给定
    \u id
    最大值
    $gt
    您试图插入的当前值的文档。由于
    \u id
    是唯一的,因此您知道只有零个或一个文档可以匹配此查询——假设存在具有该
    \u id
    的文档,如果
    最大值
    小于您插入的值,则为零,如果该值更大,则为一。此FindModify的更新部分将
    $push
    将新值推送到数组中

  • 如果且仅当步骤1失败时,使用当前尝试插入的值查找并再次修改
    \u id
    最大值
    $lte
    。在更新中,
    $push
    新值,以及
    $set
    最大值

  • 如果且仅当步骤2失败时,使用
    \u id
    查找并再次修改,并
    $push
    将新值推送到数组中。这包括在步骤1和步骤2之间,另一个线程将
    max\u值提升到大于当前插入值的值

  • 下面是实现此功能的示例Python代码:

    # the_id is the ObjectId of the document we want to modify
    # new_value is the new value to append to the list
    rslt1 = rslt2 = None
    
    rslt1 = db.collection.find_and_modify(
        {'_id': the_id, 'max_value': {'$lte': new_value}},
        {'$push': {'array': new_value}, '$set': {'max_value': new_value}})
    
    if rslt1 is None:
        rslt2 = db.collection.find_and_modify(
            {'_id': the_id},
            {'$push': {'array': new_value}})
    
    # only one of these will be non-None; this
    # picks whichever is non-None and assigns
    # it to rslt
    rslt = rslt1 or rslt2
    
    # the_id is the ObjectId of the document we want to modify
    # new_value is the new value to append to the list
    rslt1 = rslt2 = rslt3 = None
    rslt1 = db.collection.find_and_modify(
        {'_id': the_id, 'max_value': {'$gt': new_value}},
        {'$push': {'array': new_value}})
    
    if rslt1 is None:
        rslt2 = db.collection.find_and_modify(
            {'_id': the_id, 'max_value': {'$lte': new_value}},
            {'$push': {'array': new_value}, '$set': {'max_value': new_value}})
    
    if rslt1 is None and rslt2 is None:
        rslt3 = db.collection.find_and_modify(
            {'_id': the_id},
            {'$push': {'array': new_value}})
    
    # only one of these will be non-None; this
    # picks whichever is non-None and assigns
    # it to rslt
    rslt = rslt1 or rslt2 or rslt3