2015-07-07 11 views
6

Sto cercando di ottenere un comportamento "getOrCreate" utilizzando "findAndModify". Sto lavorando in nodejs utilizzando il driver nativo.Impossibile dedurre i campi di query per impostare l'errore sull'inserimento

ho:

var matches = db.collection("matches"); 
matches.findAndModify({ 
     //query 
     users: { 
      $all: [ userA_id, userB_id ] 
     }, 
     lang: lang, 
     category_id: category_id 
    }, 
    [[ "_id", "asc"]], //order 
    { 
     $setOnInsert: { 
      users: [userA_id, userB_id], 
      category_id: category_id, 
      lang: lang, 
      status: 0 
     } 
    }, 
    { 
     new:true, 
     upsert:true 
    }, function(err, doc){ 
     //Do something with doc 
    }); 

quello che stavo cercando di fare è: "Trova incontro specifico con gli utenti specificati, lingua e categoria ... se non trovato, inserire uno nuovo con i dati specificati"

Mongo sta gettando questo errore:

Error getting/creating match { [MongoError: exception: cannot infer query fields to set, path 'users' is matched twice] 
    name: 'MongoError', 
    message: 'exception: cannot infer query fields to set, path \'users\' is matched twice', 
    errmsg: 'exception: cannot infer query fields to set, path \'users\' is matched twice', 
    code: 54, 
    ok: 0 } 

c'è un modo per farlo funzionare? È impossibile?

Grazie :)

risposta

2

Non è il modo in cui "più bella" per gestire questa situazione, ma attuali restrizioni per gli operatori di selezione significa che si avrebbe bisogno di usare un'espressione JavaScript con .

Sostituendo i tuoi Vars per i valori per la facilità di esempio:

matches.findAndModify(
    { 
     "$where": function() { 
      var match = [1,2]; 
      return this.users.filter(function(el) { 
       return match.indexOf(el) != -1; 
      }).length >= 2; 
     }, 
     "lang": "en", 
     "category_id": 1 
    }, 
    [], 
    { 
     "$setOnInsert": { 
      "users": [1,2], 
      "lang": "en", 
      "category_id": 1  
     } 
    }, 
    { 
     "new": true, 
     "upsert": true 
    }, 
    function(err,doc) { 
     // do something useful here 
    } 
); 

Come si potrebbe sospettare, il "colpevole" Ecco la positional $ operator, anche se l'operazione non fa uso di esso.

E il problema specifico è a causa di $all che cerca la corrispondenza possibile in "due" posizioni nell'array. Nel caso in cui fosse richiesto un operatore "posizionale", il motore non può risolvere (attualmente) quale posizione presentare. La posizione dovrebbe essere probabilmente la "prima" corrispondenza coerente con altre operazioni, ma attualmente non funziona in questo modo.

Sostituire la logica con un'espressione JavaScript elude ciò in quanto la logica JavaScript non può restituire comunque una posizione corrispondente. Ciò rende valida l'espressione e puoi quindi "creare" e allineare i due elementi in un nuovo documento o recuperare il documento che contiene "entrambi" quegli elementi e le altre condizioni di query.


P.S Un po 'preoccupato per il tuo "tipo" qui. Potresti averlo aggiunto perché è "obbligatorio" per il metodo, tuttavia se ti aspetti che questo corrisponda a "più di un" documento e hai bisogno di "ordinarlo" per capire quale ottenere, la tua logica è leggermente imperfetta.

Quando si esegue questa operazione per "trovare o creare", allora è davvero necessario per specificare "tutti" i vincoli chiave "univoci" nella query. In caso contrario, è probabile che si verifichino errori chiave duplicati lungo la traccia.

L'ordinamento può infatti essere un array vuoto se in realtà non è necessario "prelevare" un risultato da molti.

Solo qualcosa da tenere a mente.

+0

Grazie per la risposta ... funziona come un fascino :) – Pipe

+1

c'è un altro modo? Non riesco a fare riferimento ad altre var nella funzione $ where. ReferenceError viene generato quando utilizzo una var al di fuori della funzione. –

+0

@SooChengKoh No, non c'è. Ma questa non è la tua domanda. Quindi se hai un'altra domanda, per favore [chiedi.] (Http: // StackOverflow.com/questions/ask) –

Problemi correlati