2014-09-18 16 views
7

Diciamo che ho un semplice schema:Mongoose indice univoco sul documento secondario

var testSchema = new mongoose.Schema({ 
    map: { type: [ mongoose.Schema.Types.Mixed ], default: [] }, 
    ...possibly something else 
}); 

Ora cerchiamo di assicurare che le coppie (_id, map._id) sono uniche.

testSchema.index({ _id: 1, 'map._id': 1 }, { unique: true }); 

Controllo rapido tramite db.test.getIndexes() indica che è stato creato.

{ 
    "v" : 1, 
    "unique" : true, 
    "key" : { 
     "_id" : 1, 
     "map._id" : 1 
    }, 
    "name" : "_id_1_map._id_1", 
    "ns" : "test.test", 
    "background" : true, 
    "safe" : null 
} 

Il problema è, questo indice viene ignorato e posso facilmente creare più documenti secondari con la stessa map._id. Posso facilmente eseguire query seguente più volte:

db.maps.update({ _id: ObjectId("some valid id") }, { $push: { map: { '_id': 'asd' } } }); 

e finire con seguente:

{ 
    "_id": ObjectId("some valid id"), 
    "map": [ 
     { 
      "_id": "asd" 
     }, 
     { 
      "_id": "asd" 
     }, 
     { 
      "_id": "asd" 
     } 
    ] 
} 

cosa sta succedendo qui? Perché posso inviare documenti secondari in conflitto?

+0

Possibile dupe di http://stackoverflow.com/questions/13907257/validating-uniqueness-of-an-embedded-document-scoped-by-its-parent-in-mongoose – JohnnyHK

+0

È una cattiva pratica usare qualsiasi altra cosa di ObjectId per '_id'. Perché vorresti farlo? –

risposta

14

Per farla breve: Mongo non supporta gli indici univoci per documenti secondari, anche se permette di creare loro ...

+4

... il che significa che l'indicizzazione univoca per i documenti secondari non è possibile nel modo illustrato nella domanda, ed è quello che ho scritto. –

-3

Prima lunghezza dell'oggetto in mongodb deve essere 24. Quindi è possibile disattivare _id e rinominare _id come id o altri e provare $addToSet. In bocca al lupo.

CoffeeScript esempio:

FromSchema = new Schema(
    source: { type: String, trim: true } 
    version: String 
    { _id: false }//to trun off _id 
) 

VisitorSchema = new Schema(
    id: { type: String, unique: true, trim: true } 
    uids: [ { type: Number, unique: true} ] 
    from: [ FromSchema ] 
) 

//to update 
Visitor.findOneAndUpdate(
    { id: idfa } 
    { $addToSet: { uids: uid, from: { source: source, version: version } } } 
    { upsert: true } 
    (err, visitor) -> 
    //do stuff 
+1

'_id' del sottodocumento non è un' ObjectId' quando è dichiarato come matrice di 'Mixed'. Inoltre non risponde alla domanda. –

11

Questo avviene in Google così ho pensato' d aggiungere un'alternativa all'utilizzo di un indice per ottenere un vincolo di chiave univoco come la funzionalità nei documenti secondari, spero che sia OK.

Io non sono terribilmente familiarità con Mongoose quindi è solo un aggiornamento della console mongo:

var foo = { _id: 'some value' }; //Your new subdoc here 

db.yourCollection.update(
{ '_id': 'your query here', 'myArray._id': { '$ne': foo._id } }, 
{ '$push': { myArray: { foo } }) 

Con i documenti che sembra:

{ 
    _id: '...', 
    myArray: [{_id:'your schema here'}, {...}, ...] 
} 

L'essere chiave che ci si assicura aggiornamento non restituirà un documento da aggiornare (ovvero la parte di ricerca) se la chiave del documento secondario esiste già.

Problemi correlati