2012-06-16 14 views
26

Tengo una herramienta sencilla para compilar colecciones de documentos y luego formatearlas automáticamente para EPUB o LaTeX, escrito sobre ExpressJS. Estoy usando Coffeescript, si eso importa (lo dudo).Mongoose: ObjectId Las comparaciones no son consistentes

Usando Mangosta, Tengo el siguiente:

DocumentSchema = new Schema 
    title:  String 

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

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

Offrefs no especifica a qué se refiere, ya porque quiero ser capaz de contener algunas carpetas en otras carpetas, para crear colecciones lógicas: "Estos son para la impresora, "Estos son para epub", "Estos son solo web", etc. (He eliminado todas las cosas misceláneas)

Desafortunadamente, me he encontrado con consultas donde, para recuperarlas objetos

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

Y los dos realmente se ven iguales. Pero:

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

Y una comparación visual de las dos referencias en los dos últimos, que son el mismo número de identificación, pero los ObjectId objetos no se pueden comparar correctamente.

No quiero tener que hacer conversiones de cadenas constantemente, lo cual es una gran posibilidad cuando convierto estos objetos complejos en árboles de datos. Las relaciones de árbol son un oso en cualquier DB; no deberían ser difíciles en MongoDB.

¿Cómo se hace las comparaciones con ObjectId en MongoDB?

Respuesta

76

Una comparación recta de == (o ===) comparará los dos objetos por referencia, no por valor. Entonces eso solo evaluará a verdadero si ambos hacen referencia a la misma instancia.

En su lugar, usted debe utilizar el método de ObjectIDequals para comparar sus valores:

story._id.equals(offref.ref) 

Como @bendytree notas en los comentarios, si cualquiera de los valores podría ser nulo (y quiere nulos que resultan ser iguales), a continuación, puede utilizar el siguiente lugar:

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

Yay, características no documentadas. – peterjwest

+0

¿Entonces esto no es lo mismo que mongoose.Schema.Types.ObjectID? Su documentación implica que solo tiene el método 'auto': http://mongoosejs.com/docs/api.html#schema-objectid-js – peterjwest

+1

@peterjwest Correcto, 'mongoose.Schema.Types.ObjectId' es realmente solo para usar como metadatos de campo en las definiciones de esquema. – JohnnyHK

1

Esto va un poco más allá de la pregunta original, pero he encontrado que el método de objeto de .equals del regresará falsa en algunos casos en los que una comparación de cadenas volverá verdadero incluso cuando los valores no son nulos. Ejemplo:

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

Salida:

compare1: true; compare2: false; compare3: true 

Esto ocurrió cuando invitationOwningUser (un ID de objeto) procedía de una colección creada usando un esquema Mangosta, y linkedOwningUser (también un ID de objeto) procedía de una colección no se ha creado usando Mangosta (solo métodos MongoDB regulares).

Aquí es el documento que contiene invitationOwningUser (el campo owningUser):

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

Aquí es el documento que contiene linkedOwningUser (el campo owningUser):

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

Por lo tanto, como una línea de fondo para mí , Utilizaré la técnica de comparación de cadenas para comparar los ObjectID, no el método .equals.

+0

Esto parece ser un problema crítico. ¿Sabes por qué Mongoose no los ve de la misma manera? Supongo que es 'if (! Buffer.isBuffer (otro))' en el 'MongooseBuffer.mixin.equals' que parece ser una optimización para guardar el escaneo de los contenidos. ¡Estoy preocupado ahora! Acabo de convertir mi .toString a .equals. (Pero solo uso mangosta == mangosta, así que supongo que no es un riesgo). – scipilot

Cuestiones relacionadas