【问题标题】:Mongoose: ObjectId Comparisons fail inconsistentlyMongoose:ObjectId 比较失败不一致
【发布时间】:2012-06-19 02:04:54
【问题描述】:

我有一个简单的工具,用于构建文档集合,然后自动将它们格式化为 EPUB 或 LaTeX 渲染,它是在 ExpressJS 之上编写的。我正在使用 Coffeescript,如果这很重要(我对此表示怀疑)。

使用猫鼬,我有以下几点:

DocumentSchema = new Schema
    title:     String

Offrefs = new Schema
    ref:       { type: ObjectId }
    isa:       String

BinderSchema = new Schema
    title:     String
    contains:  [Offrefs]

Offrefs 没有指定它所指的内容,因为我希望能够在其他活页夹中包含一些活页夹,以创建逻辑集合:“这些用于打印机”、“这些用于 epub”、“这些是仅限网络,”等等(我已经去掉了所有杂项。)

不幸的是,我遇到了检索对象的查询

(story._id == offref.ref) -> True 

而且两者确实看起来一样。但是:

(binder._id == offref.ref) -> False
(String(binder._id) == String(offref.ref)) -> True

最后两个引用的视觉比较,它们相同的 ID 号,但 ObjectId 对象没有正确比较。

我不想不断地进行字符串转换,当我将这些复杂的对象转换为数据树时,这是一个很大的可能性。树关系在任何数据库中都是熊;它们在 MongoDB 中应该不难。

如何在 MongoDB 中进行 ObjectId 比较?

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    直接的==(或===)比较将通过引用而不是值来比较两个对象。因此,只有当它们都引用同一个实例时,才会评估为 true。

    相反,您应该使用ObjectIDequals 方法来比较它们的值:

    story._id.equals(offref.ref)
    

    正如@bendytree 在 cmets 中的注释,如果任一值都可以为 null(并且您希望 null 比较为相等),那么您可以改用以下内容:

    String(story._id) === String(offref.ref)
    

    【讨论】:

    • 是的,未记录的功能。
    • 所以这和 mongoose.Schema.Types.ObjectID 不一样?他们的文档暗示它只有“自动”方法:mongoosejs.com/docs/api.html#schema-objectid-js
    • @peterjwest 对,mongoose.Schema.Types.ObjectId 实际上只是用作模式定义中的字段类型元数据。
    • 不幸的是,.equals() 如果任何一个 id 为空,就会抛出异常。 String(...) == String(...) 似乎是最安全的选择。
    【解决方案2】:

    这有点超出了最初提出的问题,但我发现 ObjectID 的 .equals 方法在某些情况下会返回 false,即使值不为 null,字符串比较也会返回 true。示例:

    var compare1 = invitationOwningUser.toString() === linkedOwningUser.toString();
    var compare2 = invitationOwningUser.equals(linkedOwningUser);
    var compare3 = String(invitationOwningUser) === String(linkedOwningUser);
    logger.debug("compare1: " + compare1 + "; " + "compare2: " + compare2 + "; " + "compare3: " + compare3);
    

    输出:

    compare1: true; compare2: false; compare3: true 
    

    当invitationOwningUser(一个ObjectID)来自一个使用Mongoose架构创建的集合,而linkedOwningUser(也是一个ObjectID)来自一个不是使用Mongoose创建的集合(只是常规的MongoDB方法)时,就会发生这种情况。

    这里是包含invitationOwningUser(owningUser 字段)的文档:

    {
        "_id" : ObjectId("5782faec1f3b568d58d09518"),
        "owningUser" : ObjectId("5781a5685a06e69b158763ea"),
        "capabilities" : [
            "Read",
            "Update"
        ],
        "redeemed" : true,
        "expiry" : ISODate("2016-07-12T01:45:18.017Z"),
        "__v" : 0
    }
    

    这是包含linkedOwningUser(owningUser 字段)的文档:

    {
        "_id" : ObjectId("05fb8257c95d538d58be7a89"),
        "linked" : [
            {
                "owningUser" : ObjectId("5781a5685a06e69b158763ea"),
                "capabilities" : [
                    "Read",
                    "Update"
                ]
            }
        ]
    }
    

    所以,作为我的底线,我将使用字符串比较技术来比较 ObjectID,而不是 .equals 方法。

    【讨论】:

    • 这似乎是一个关键问题。你知道为什么猫鼬不认为他们是一样的吗?我猜它是MongooseBuffer.mixin.equals 中的if (!Buffer.isBuffer(other)),这似乎是节省扫描内容的优化。我现在很担心!我刚刚将我的 .toString 转换为 .equals。 (但我只使用 mongoose==mongoose,所以我想这不是风险)。
    猜你喜欢
    • 2018-10-27
    • 2017-11-26
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多