2015-05-15 28 views
15

Ho una tabella sondaggio che assomiglia così:RethinkDB - Aggiornamento array nidificato

{ 
    id: Id, 
    date: Date, 
    clients: [{ 
    client_id: Id, 
    contacts: [{ 
     contact_id: Id, 
     score: Number, 
     feedback: String, 
     email: String 
    }] 
    }] 
} 

devo aggiornati i campi score e feedback sotto un contatto specifico. Attualmente, sto facendo funzionare l'aggiornamento in questo modo:

function saveScore(obj){ 
    var dfd = q.defer(); 
    var survey = surveys.get(obj.survey_id); 

    survey 
    .pluck({ clients: 'contacts' }) 
    .run() 
    .then(results => { 

     results.clients.forEach((item, outerIndex) => { 
     item.contacts.forEach((item, index, array) => { 
      if(Number(item.contact_id) === Number(obj.contact_id)) { 
      array[index].score = obj.score; 
      console.log(outerIndex, index); 
      } 
     }); 
     }); 

     return survey.update(results).run() 
    }) 
    .then(results => dfd.resolve(results)) 
    .catch(err => dfd.resolve(err)); 

    return dfd.promise; 
}; 

Quando guardo il metodo update, specifica come aggiornare chiave annidati: coppie di valori. Tuttavia, non riesco a trovare alcun esempio per aggiornare un singolo elemento in un array.

C'è un modo migliore e, auspicabilmente, più pulito per aggiornare gli elementi in un array annidato?

risposta

10

Potrebbe essere necessario ottenere l'array, filter, il valore desiderato nell'array e quindi aggiungerlo nuovamente all'array. Quindi è possibile passare la matrice aggiornata al metodo update.

Esempio

Diciamo che ha un documento con due clienti che entrambi hanno un name e un score e si desidera aggiornare il punteggio in uno di essi:

{ 
    "clients": [ 
    { 
     "name": "jacob" , 
     "score": 200 
    } , 
    { 
     "name": "jorge" , 
     "score": 57 
    } 
    ] , 
    "id": "70589f08-284c-495a-b089-005812ec589f" 
} 

È possibile ottenere quel documento specifico, eseguire il comando update con una funzione anonimo e quindi passare il nuovo array aggiornato nella proprietà clients.

r.table('jacob').get("70589f08-284c-495a-b089-005812ec589f") 
    .update(function (row) { 
    return { 
     // Get all the clients, expect the one we want to update 
     clients: row('clients').filter(function (client) { 
     return client('name').ne('jorge') 
     }) 
     // Append a new client, with the update information 
     .append({ name: 'jorge', score: 57 }) 
    }; 
    }); 

io credo che questo è un po 'ingombrante e probabilmente c'è un modo più bello più elegante di fare questo, ma questo dovrebbe risolvere il problema.

Schema del database

Forse vale la pena di creare una tabella contacts per tutti i contatti e poi fare un qualche tipo di unirsi a voi i dati. Allora la vostra proprietà contacts nella vostra clients matrice sarebbe simile:

{ 
    id: Id, 
    date: Date, 
    clients: [{ 
    client_id: Id, 
    contact_scores: { 
     Id: score(Number) 
    }, 
    contact_feedbacks: { 
     Id: feedback(String) 
    } 
    }] 
} 
3

funziona per me

r.table(...).get(...).update({ 
contacts: r.row('Contacts').changeAt(0, 
    r.row('Contacts').nth(0).merge({feedback: "NICE"})) 
}) 
0

schema del database

{ 
    "clients": [ 
    { 
     "name": "jacob" , 
     "score": 200 
    } , 
    { 
     "name": "jorge" , 
     "score": 57 
    } 
    ] , 
    "id": "70589f08-284c-495a-b089-005812ec589f" 
} 

allora si può fare in questo modo utilizzando map e branch query.

r.db('users').table('participants').get('70589f08-284c-495a-b089-005812ec589f') 
    .update({"clients": r.row('clients').map(function(elem){ 
    return r.branch(
     elem('name').eq("jacob"), 
     elem.merge({ "score": 100 }), 
     elem)}) 
    }) 
Problemi correlati