Подтвердить что ты не робот

Mongoose: ObjectId Сравнение несовместимы

У меня есть простой инструмент для создания коллекций документов, а затем автоматически их форматирование для рендеринга EPUB или LaTeX, написанного поверх ExpressJS. Я использую Coffeescript, если это имеет значение (я сомневаюсь).

Используя Mongoose, у меня есть следующее:

DocumentSchema = new Schema
    title:     String

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

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

Offrefs не указывает, к чему это относится, потому что я хочу иметь возможность содержать некоторые связующие в других связующих, создавать логические коллекции: "Это для принтера", "Это для epub", "Это web only" и т.д. (я удалил все разные вещи.)

К сожалению, я столкнулся с запросами, где для восстановленных объектов

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

И оба действительно выглядят одинаково. Но:

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

И визуальное сравнение двух ссылок в последних двух, они имеют одинаковый идентификационный номер, но объекты ObjectId не сравниваются правильно.

Я не хочу постоянно выполнять преобразования строк, что является сильной возможностью, когда я конвертирую эти сложные объекты в деревья данных. Деревовые отношения - медведь в любой БД; они не должны быть трудными в MongoDB.

Как вы выполняете сравнения ObjectId в MongoDB?

4b9b3361

Ответ 1

Прямое сравнение == (или ===) будет сравнивать два объекта по ссылке, а не по значению. Таким образом, это будет оцениваться только в true, если они ссылаются на один и тот же экземпляр.

Вместо этого вы должны использовать equals метод ObjectID для сравнения их значений:

story._id.equals(offref.ref)

Как примечания @bendytree в комментариях, если любое значение может быть нулевым (и вы хотите, чтобы нули сравнивались как равные), вы можете вместо этого использовать следующее:

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

Ответ 2

Это несколько выходит за исходный заданный вопрос, но я обнаружил, что метод .equals ObjectID вернет false в некоторых случаях, когда сравнение строк вернет 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 

Это произошло, когда приглашение InvOwningUser (ObjectID) появилось из коллекции, созданной с использованием схемы Mongoose, а связанныйOwningUser (также ObjectID) появился из коллекции, не созданной с использованием Mongoose (только обычные методы MongoDB).

Вот документ, содержащий приглашениеOwningUser (поле 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.