2013-05-21 7 views
28

questa è la mia collezione appuntamentocome utilizzare il popolamento e l'aggregazione nella stessa istruzione?

{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") } 

{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") } 

{ _id: ObjectId("518ee0bc9be1909012000002"), date: ISODate("2013-05-13T22:00:00Z"), patient:ObjectId("518ee0bc9be1909012000002") } 

io uso aggregata per ottenere il risultato

{date: ISODate("2013-05-13T22:00:00Z"), 
patients:[ObjectId("518ee0bc9be1909012000002"),ObjectId("518ee0bc9be1909012000002"),ObjectId("518ee0bc9be1909012000002")] } 

come questo

Appointments.aggregate([ 
{$group: {_id: '$date', patients: {$push: '$patient'}}}, 
{$project: {date: '$_id', patients: 1, _id: 0}} 
], ...) 

come si può compilare il documento paziente provo questo, ma non funziona .. Appointments.find({}).populate("patient").aggregate ....

in altre parole, posso usare il popolare e aggregata stessa istruzione

qualsiasi aiuto per favore

+0

Considerare di cambiare la risposta accettata alla risposta di ruffrey come Mongoose ora supporta questo. – JohnnyHK

risposta

50

Con l'ultima versione di mangusta (mangusta> = 3.6), è possibile ma richiede una seconda query, e utilizzando popolano in modo diverso. Dopo la vostra aggregazione, fare questo:

Patients.populate(result, {path: "patient"}, callback); 

saperne di più visita il Mongoose API e Mongoose docs.

+0

ho incorporato la matrice del documento e come fornire il valore da quel documento al percorso nella risposta di cui sopra. Il documento è un po 'come [{"da": "objectId", "text": "Questo è testing", "date": "date"}] voglio dare il percorso: da in sopra la risposta. –

+0

Vedere la domanda originale su questo - '" paziente "' è una delle chiavi per i documenti in una matrice. Nel tuo esempio, supponiamo che 'Message' sia un modello di mangusta. 'Message.populate (result, {paths:" da "}, callback);' – ruffrey

+1

Per popolare 2 percorsi, aggiungi l'elenco di percorsi Message.populate (result, {paths: "path1 path2 path3"}, callback); –

10

Risposta breve: Non è possibile.

Risposta lunga: Nel quadro di aggregazione, i campi restituiti sono costruiti da te, e tu sei in grado di "rinominare" le proprietà del documento.

Ciò significa che Mongoose non è in grado di identificare che i documenti di riferimento saranno disponibili nel risultato finale.

La cosa migliore che è possibile fare in tale situazione è compilare il campo desiderato dopo che la query è stata restituita. Sì, ciò comporterebbe due chiamate DB, ma è ciò che MongoDB ci consente di fare.

Un po 'come questo:

Appointments.aggregate([ ... ], function(e, result) { 
    if (e) return; 

    // You would probably have to do some loop here, as probably 'result' is array 
    Patients.findOneById(result.patient, function(e, patient) { 
    if (e) return; 

    result.patient = patient; 
    }); 
}); 
+0

La risposta seguente fornisce un modo leggermente più semplice per eseguire l'operazione. Non c'è bisogno di scrivere il tuo loop. – pehaada

16

È possibile utilizzare la ricerca $ che è simile a popolare.

In un esempio non correlato, io uso $ partita per interrogare per i record e $ di ricerca per compilare un modello straniero come un sub-proprietà di questi record:

Invite.aggregate(
     { $match: {interview: req.params.interview}}, 
     { $lookup: {from: 'users', localField: 'email', foreignField: 'email', as: 'user'} } 
    ).exec(function (err, invites) { 
     if (err) { 
     next(err); 
     } 

     res.json(invites); 
    } 
); 
+0

Eccellente, a volte la risposta migliore è la più semplice di tutte, non sapevo che il comando di ricerca prendesse i risultati della partita che era la mia confusione. – shontauro

7

eseguire un join con $ lookup

A ordina raccolta contiene i seguenti documenti:

{ "_id" : 1, "item" : "abc", "price" : 12, "quantity" : 2 } 
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1 } 
{ "_id" : 3 } 

Un altro inventario raccolta contiene i seguenti documenti:

{ "_id" : 1, "sku" : "abc", description: "product 1", "instock" : 120 } 
{ "_id" : 2, "sku" : "def", description: "product 2", "instock" : 80 } 
{ "_id" : 3, "sku" : "ijk", description: "product 3", "instock" : 60 } 
{ "_id" : 4, "sku" : "jkl", description: "product 4", "instock" : 70 } 
{ "_id" : 5, "sku": null, description: "Incomplete" } 
{ "_id" : 6 } 

la seguente operazione di aggregazione per la raccolta ordini si unisce ai documenti da ordini con i documenti della collezione di inventario utilizzando la voce campi dalla raccolta ordini e il campo sku dalla raccolta di inventario:

db.orders.aggregate([ 
    { 
     $lookup: 
     { 
      from: "inventory", 
      localField: "item", 
      foreignField: "sku", 
      as: "inventory_docs" 
     } 
    } 
]) 

L'operazione restituisce i seguenti documenti:

{ 
    "_id" : 1, 
    "item" : "abc", 
    "price" : 12, 
    "quantity" : 2, 
    "inventory_docs" : [ 
    { "_id" : 1, "sku" : "abc", description: "product 1", "instock" : 120  } 
    ] 
} 
{ 
    "_id" : 2, 
    "item" : "jkl", 
    "price" : 20, 
    "quantity" : 1, 
    "inventory_docs" : [ 
    { "_id" : 4, "sku" : "jkl", "description" : "product 4", "instock" : 70 } 
    ] 
} 
{ 
    "_id" : 3, 
    "inventory_docs" : [ 
    { "_id" : 5, "sku" : null, "description" : "Incomplete" }, 
    { "_id" : 6 } 
    ] 
} 

Reference $lookup

1

enter image description here

domain.Farm.aggregate({ 
    $match: { 
     "_id": mongoose.Types.ObjectId(farmId) 
    } 
}, { 
    $unwind: "$SelfAssessment" 
}, { 
    $match: { 
     "SelfAssessment.questionCategoryID": QuesCategoryId, 
     "SelfAssessment.questionID": quesId 
    } 
},function(err, docs) { 
     var options = { 
      path: 'SelfAssessment.actions', 
      model: 'FarmAction' 
    }; 
    domain.Farm.populate(docs, options, function (err, projects) { 
     callback(err,projects); 

     }); 

}); 

risultati che ho ottenuto modello di azione popolano

{ "error": false, "object": [ 
    { 
     "_id": "57750cf6197f0b5137d259a0", 
     "createdAt": "2016-06-30T12:13:42.299Z", 
     "updatedAt": "2016-06-30T12:13:42.299Z", 
     "farmName": "abb", 
     "userId": "57750ce2197f0b5137d2599e", 
     "SelfAssessment": { 
     "questionName": "Aquatic biodiversity", 
     "questionID": "3kGTBsESPeYQoA8ae2Ocoy", 
     "questionCategoryID": "5aBe7kuYWIEoyqWCWcAEe0", 
     "question": "Waterways protected from nutrient runoff and stock access through fencing, buffer strips and off stream watering points", 
     "questionImage": "http://images.contentful.com/vkfoa0gk73be/4pGLv16BziYYSe2ageCK04/6a04041ab3344ec18fb2ecaba3bb26d5/thumb1_home.png", 
     "_id": "57750cf6197f0b5137d259a1", 
     "actions": [ 
      { 
      "_id": "577512c6af3a87543932e675", 
      "createdAt": "2016-06-30T12:38:30.314Z", 
      "updatedAt": "2016-06-30T12:38:30.314Z", 
      "__v": 0, 
      "Evidence": [], 
      "setReminder": "", 
      "description": "sdsdsd", 
      "priority": "High", 
      "created": "2016-06-30T12:38:30.312Z", 
      "actionTitle": "sdsd" 
      } 
     ], 
     "answer": "Relevant" 
     }, 
     "locations": [] 
    } ], "message": "", "extendedMessage": "", "timeStamp": 1467351827979 } 
1

Lo si può fare in una query come questa:

Appointments.aggregate([{ 
     $group: { 
      _id: '$date', 
      patients: { 
       $push: '$patient' 
      } 
     } 
    }, 
    { 
     $project: { 
      date: '$_id', 
      patients: 1, 
      _id: 0 
     } 
    }, 
    { 
     $lookup: { 
      from: "patients", 
      localField: "patient", 
      foreignField: "_id", 
      as: "patient_doc" 
     } 
    } 
]) 

popolano utilizza fondamentalmente $ ricerca sotto la foresta. in questo caso non c'è bisogno di una seconda query. per ulteriori dettagli check MongoDB aggregation lookup

Problemi correlati