【问题标题】:Mongoose ignores $ne while updating documentMongoose 在更新文档时忽略 $ne
【发布时间】:2015-04-07 03:51:48
【问题描述】:

我正在为后端使用 Node、Mongoose 和 Socket.io 构建一个持久的 html 字段框架。我在 Mongoose 的更新方法中遇到了一个错误。

mongo 中的文档是这样的:

{
    "_id" : "pickable_qty",
    "currently_connected" : [ ],
    "locks" : [
        {
            socket_id: 'eQYVyz1z28rJZRPpAAAB',
            unique_values:{
                merchant_warehouse_id: 11.1,
                product_item_id: 5555
            }
        },
        {
            socket_id: 'eQYVyz1z28rJZRPpAAAB',
            unique_values:{
                merchant_warehouse_id: 11.2,
                product_item_id: 5555
            }
        },
        {
            socket_id: 'eQYVyz1z28rJZRPpAAAB',
            unique_values:{
                merchant_warehouse_id: 11.1,
                product_item_id: 1234
            }
        }
    ],
    "definition" : {
        "ajax_url" : "/persistent-fields/pickable_qty",
        "unique_keys" : [
            "product_item_id",
            "merchant_warehouse_id"
        ],
        "max_idle_seconds" : 30,
        "field_type" : "text"
    },
    "__v" : 0
}

当我开始将子文档插入locks 数组时出现问题。

我使用 Mongoose 的 update 方法插入它们,如下所示:

FieldSchema.update(
    {
        _id: 'pickable_qty',
        'locks.unique_values': { 
            '$ne': { 
                merchant_warehouse_id: 11.1, 
                product_item_id: 5334 
            } 
        },
        'definition.unique_keys': { 
            '$all': [ 
                'merchant_warehouse_id', 
                'product_item_id' 
            ] 
        } 
    },
    {
        '$push': {
            locks: { 
                socket_id: 'eQYVyz1z28rJZRPpAAAB', 
                unique_values: {
                    merchant_warehouse_id: 11.1, 
                    product_item_id: 5334 
                } 
            } 
        }
    },
    function(err, count, res){
        console.log('err:', err, 'count:', count, 'res:', res);
        //err: null count: 1 res: { ok: true, n: 1, updatedExisting: true }
    }
);

第一次插入完全符合预期,在包含唯一值 {merchant_warehouse_id: 11.1,product_item_id: 5334} 的数组中没有 locks,因此找到了文档并插入了 lock 子文档。

但是,第二次运行相同的更新不应该插入新的locks 子文档,因为已经存在具有相同unique_values 的子文档,并且查询的$ne 部分应该会导致它返回没有匹配的更新。

我已经确认使用相同的查询执行 find 在 MongoDB 命令行和使用 Mongoose 自己的 Schema.find 方法时都不会返回任何文档,但 Schema.update 方法仍然会找到一个文档并插入一个重复的 @987654334 @子文档。

我是不是快疯了,还是有什么原因导致 Mongoose 的 find 方法无法检索文档而 update 会检索到文档?

【问题讨论】:

    标签: node.js mongodb mongoose socket.io


    【解决方案1】:

    问题是您正在查询一个对象是否与子文档匹配,这可能很棘手。您想在查询中使用 $elemMatch 和 $ne 的组合。

    var query = {
        _id: 'pickable_qty',
        'locks': { 
            $elemMatch: {
                merchant_warehouse_id: {
                    $ne: 11.1
                },
                product_item_id: {
                    $ne: 5334
                }
            }
        },
        'definition.unique_keys': { 
            '$all': [ 
                'merchant_warehouse_id', 
                'product_item_id' 
            ] 
        } 
    }
    

    它基本上是对数组内的文档的查询。

    【讨论】:

    • 感谢您的回复,但我似乎无法让该查询检索任何文档,即使 locks 为空并省略 $all 也是如此。除了在 Mongoose 的 update 方法的上下文中之外,原始查询的工作似乎很奇怪
    • @RazVarren 你能在你的 mongo shell 中试试这个吗?
    • 是的,我在 mongo shell 和 mongoose 的 update 方法上都试过了。我无法使用它检索任何带有空 locks 的文档。
    • 如何使用锁:{$ne: []} 以及?
    • 如果数组中至少有一个子文档,则使用locks:{$ne:[]} 确实匹配,但我要防止出现重复的locks。我已经更新了原始帖子以显示我认为在数据库中独特的 locks 的列表。基本上我想防止猫鼬插入第二个locks 子文档,其中包含相同的unique_values"locks.unique_values":{$ne: {merchant_warehouse_id: 11.1, product_item_id: 5334}} 在 mongo shell 的 findupdate 中正是这样做的。使用猫鼬的find 也可以正常工作,但猫鼬的update 似乎忽略了$ne
    【解决方案2】:

    使用 MongoDB 的查询分析器后,我发现 Mongoose 在执行更新查询时正在切换 lockunique_values 对象中的键顺序。然后它以正确的顺序插入带有键的重复子文档。所以显然 MongoDB 的 $ne 运算符将匹配嵌套的子文档数组,前提是子文档中的键与您的查询的顺序相同。

    【讨论】:

    • 一般来说,MongoDB 中子文档的相等性测试取决于键顺序,请参阅 MongoDB 手册中的 exact match on embedded documents。这可能不是人们所期望的。 Mongoose 应该知道并考虑到这一点 - 我会考虑在 Mongoose Github 项目中提交一个问题,看看这种行为是否是故意的。
    • 我认为问题在于因为我使用的是Node,而Node是Javascript,所以对象键实际上是don't have an order
    猜你喜欢
    • 2015-02-09
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 2015-02-19
    • 2021-10-23
    • 2014-06-12
    相关资源
    最近更新 更多