2012-06-16 16 views
26

Mam proste narzędzie do tworzenia kolekcji dokumentów, a następnie automatycznego formatowania ich do renderowania EPUB lub LaTeX, napisanego na ExpressJS. Używam Coffeescript, jeśli to ma znaczenie (wątpię w to).Mongoose: ObjectId Porównania nie działają niekonsekwentnie

Korzystanie Mongoose, mam następujący:

DocumentSchema = new Schema 
    title:  String 

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

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

Offrefs nie precyzuje, co to oznacza, bo, ponieważ chcę, aby móc zawierać pewne spoiwa w innym spoiwem, aby tworzyć zbiory logiczne: „To są dla drukarki, "" Są to dla epub "," To są tylko sieci ", itp. (usunąłem wszystkie inne rzeczy).

Niestety, natknąłem się na zapytania, w których, do odzyskania obiekty

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

Te dwie rzeczy wyglądają tak samo. Ale:

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

I wizualne porównanie dwóch odwołań w ciągu ostatnich dwóch, one ten sam numer ID, ale ObjectId obiekty nie porównać poprawnie.

Nie chcę stale wykonywać konwersji ciągów znaków, co jest dużą szansą, gdy konwertuję te złożone obiekty na drzewa danych. Relacje drzew są niedźwiedziami w dowolnej bazie danych; nie powinny być trudne w MongoDB.

W jaki sposób porównasz ObjectId w MongoDB?

Odpowiedz

76

Proste porównanie == (lub ===) spowoduje porównanie dwóch obiektów przez odniesienie, a nie wartości. Tak więc będzie to tylko prawda, jeśli obie odnoszą się do tej samej instancji.

Zamiast tego należy używać metody ObjectIDequals porównać ich wartości:

story._id.equals(offref.ref) 

As @bendytree notatki w komentarzach, jeśli jedna wartość może być null (null i chcesz porównać jako równe), a następnie można użyć następujących zamiast:

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

Yay, nieudokumentowane funkcje. – peterjwest

+0

Więc to nie to samo, co mongoose.Schema.Types.ObjectID? Ich dokumentacja sugeruje, że ma tylko metodę "auto": http://mongoosejs.com/docs/api.html#schema-objectid-js – peterjwest

+1

@peterjwest Prawda, 'mongoose.Schema.Types.ObjectId' jest naprawdę tylko do użycia jako metadane typu pola w definicjach schematów. – JohnnyHK

1

To idzie nieco poza oryginalnym zadawane pytanie, ale okazało się, że metoda .equals z ObjectID będzie return false w niektórych przypadkach porównanie ciąg powróci prawda, nawet jeśli wartości nie są zerowe. Przykład:

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); 

wyjściowa:

compare1: true; compare2: false; compare3: true 

Nastąpiło to po invitationOwningUser (an ObjectID) pochodzi z kolekcji utworzonych za pomocą schematu Mongoose, a linkedOwningUser (również ObjectID) pochodzi z kolekcji nie utworzonym za pomocą Mongoose (tylko regularne metody MongoDB).

Oto dokument zawierający invitationOwningUser (pole owningUser):

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

Oto dokument zawierający linkedOwningUser (pole owningUser):

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

Tak, jak w dolnym wierszu dla mnie Użyję techniki porównywania ciągów do porównania metody ObjectID, a nie metody .equals.

+0

To wydaje się krytycznym problemem. Czy wiesz, dlaczego Mongoose nie postrzega ich jako takich samych? Zgaduję, że to 'if (! Buffer.isBuffer (other))' w 'MongooseBuffer.mixin.equals', który wydaje się być optymalizacją do zapisywania zawartości. Martwię się teraz! Właśnie przekonwertowałem moje .toString na .equals. (ale używam tylko mangusty == mangusta, więc myślę, że to nie jest ryzyko). – scipilot

Powiązane problemy