我有一个保存"Item"数据的集合 case ,带有必需的 node "Owner"和可选的 node "Status".

{ _id: 123, item: {some: "data 123" }, owner: {id: 456} }
{ _id: 124, item: {some: "data 124" }, owner: {id: 789}, status: { ok: 1} }

当插入新记录时,如果新的owner.id等于旧的owner.id,那么我希望新记录具有相同的status

用SQL表示,它应该是这样的

INSERT INTO mytable 
(
    id, 
    item_some,
    owner_id,
    status_ok
) 
 VALUES (
    125, 
    'data 125', 
    789, 
    (SELECT COALESCE(status_ok, null) FROM mytable WHERE owner_id=789 LIMIT 1) 
);

我看着$expr,但不确定如何在db.collection.insert()使用它... 提前谢谢你

推荐答案

我建议你先执行findOne,如下所示:

const newObj = { item: {some: "data 123" }, owner: {id: 456} };
const prevObj = db.collection.findOne( {"owner._id": newObj.owner.id , status: {$exists: true}});
if (prevObj) {
    newObj.status = prevObj.status
}

db.collection.insertOne(newObj)

这基本上就是您的SQL查询所做的,在Mongo中不可能只用一次调用就能做到这一点.(我将使用聚合管道和$merge阶段附加一种"老套"的方法来实现这一点,但我不建议您使用它,因为它有很多开销,而且还需要集合中至少1个文档)

db.collection.aggregate([
    {
        $facet: {
            new: [
                {
                    $limit: 1
                },
                {
                    $replaceRoot: {
                        newRoot: newObj
                    }
                }
            ],
            old: [
                {
                    $match: {
                        "owner.id": newObj.owner.id,
                        status: {$exists: true}
                    }
                }
            ]
        },
    },
    {
       $replaceRoot: {
           newRoot: {
                $mergeObjects: [
                    {
                        $arrayElemAt: ["$new", 0]
                    },
                    {
                        $cond: [
                            {
                              $ne: [
                                  {
                                      $arrayElemAt: ["$old", 0]
                                  },
                                  null
                              ]
                            },
                            {
                                status: {
                                    $getField: {
                                        field: "status",
                                        input: {
                                            $arrayElemAt: ["$old", 0]
                                        }
                                    }
                                }
                            },
                            {}
                        ]
                    }
                ]
           }
       }
    },
    {
        $merge: {
            into: "collection",
            whenNotMatched: "insert"
        }
    }
])

Mongo Playground

Mongodb相关问答推荐

$mod只支持数字类型,不支持MongoDb中的array和int

MongoDB 对特定搜索查询的响应时间较长

MongoDB 在一个聚合中包含多个组

有没有一种方法可以找到一个文档并通过 Go 更改 mongodb 中的 id/value 来克隆它

以聚合顺序使用 $$ROOT

将 MongoDB BsonDocument 转换为字符串

子文档上的mongoose唯一索引

将MongoDB连接到前端?

获取收集字节使用情况统计信息的pymongo方法?

Node.js 和 Passport 对象没有方法 validPassword

如何在 Node.js 中格式化 Mongoose 的日期?

直接从 URL 查询字符串提供的 mongo 查询有多危险?

MongoDB 范围查询中 $lt 和 $gt 的顺序

如何将转储文件夹导入 mongodb 数据库?

在mongoose中查询虚拟属性

错误:需要数据和盐参数

MongoDB 的 MMAPV1、WiredTiger 或 In-Memory StorageEngine 如何 Select ?

哪个数据库适合我的应用程序 mysql 或 mongodb ?使用 Node.js 、 Backbone 、 Now.js

如何从集合中删除除 MongoDB 中的文档之外的所有文档

如何将 Geojson 文件导入 MongoDB