Geben Sie bestimmte Felder mit .populate () von Mongoose zurück


82

Ich erhalte einen JSON-Wert von MongoDB, nachdem ich meine Abfrage ausgeführt habe. Das Problem ist, dass ich nicht alle mit meiner Rückgabe verbundenen JSON-Daten zurückgeben möchte. Ich habe versucht, die Dokumente zu durchsuchen, und keinen geeigneten Weg gefunden, dies zu tun. Ich habe mich gefragt, was ist, wenn es möglich ist, und wenn ja, wie ist das richtig? Beispiel: In der DB

{
    user: "RMS",
    OS: "GNU/HURD",
    bearded: "yes",
    philosophy: {
        software: "FOSS",
        cryptology: "Necessary"
    },
    email: {
        responds: "Yes",
        address: "rms@gnu.org"
    },
    facebook: {}
}

{
    user: "zuckerburg",
    os: "OSX",
    bearded: "no",
    philosophy: {
        software: "OSS",
        cryptology: "Optional"
    },
    email: {},
    facebook: {
        responds: "Sometimes",
        address: "https://www.facebook.com/zuck?fref=ts"
    }
} 

Was wäre der richtige Weg, um ein Feld zurückzugeben, wenn es für einen Benutzer existiert, aber wenn es kein anderes Feld zurückgibt. Für das obige Beispiel möchte ich das [email][address]Feld für RMS und das [facebook][address]Feld für Zuckerburg zurückgeben. Dies ist, was ich versucht habe zu finden, wenn ein Feld null ist, aber es scheint nicht zu funktionieren.

 .populate('user' , `email.address`)
  .exec(function (err, subscription){ 
    var key;
    var f;
    for(key in subscription){
      if(subscription[key].facebook != null  ){
          console.log("user has fb");
      }
    }
  }

Antworten:


89

Mir ist nicht ganz klar, was Sie unter "Zurückgeben eines Feldes" verstehen, aber Sie können eine lean()Abfrage verwenden, um die Ausgabe frei zu ändern, dann beide Felder auszufüllen und das Ergebnis nachzubearbeiten, um nur das gewünschte Feld beizubehalten:

.lean().populate('user', 'email.address facebook.address')
  .exec(function (err, subscription){ 
    if (subscription.user.email.address) {
        delete subscription.user.facebook;
    } else {
        delete subscription.user.email;
    }
  });

1
Das funktioniert bei mir nicht. Weiß jemand, ob sich dies mit einem Mongoose-Update geändert hat?
Ninja Coding

1
Dies ist nicht für mich arbeiten entweder, habe ich versucht .populate('model', 'field'), .populate('model', { field: 1}), .populate('model', [field])mit und ohne lean()und mit und ohne selectPopulatedPaths: falseauf dem Modell , aber ich habe immer das volle besiedelte Objekt in der Antwort. Die Dokumentation besagt, dass Ihre Antwort die richtige sein soll, aber ich kann sie nicht zum Laufen bringen. Hat jemand das gleiche Problem?
Mel-Mouk

51

Wenn Sie nur einige bestimmte Felder für die aufgefüllten Dokumente zurückgeben möchten, können Sie dies erreichen, indem Sie die Feldnamensyntax als zweites Argument an die Auffüllmethode übergeben.

Model
.findOne({ _id: 'bogus' })
.populate('the_field_to_populate', 'name') // only return the Persons name
...

Siehe Feldauswahl für Mungo-Felder


7
Funktioniert gut. Sie können auch mehr Felder zurückgeben, nur müssen Sie mehr Felder übergeben. -> bevölkern ('the_field_to_populate', 'name lastname')
slorenzo

Was wäre, wenn Sie mehr als ein Modell zum Ausfüllen hätten und Felder für diese wollten? Wie bevölkern ('Benutzer Beiträge', 'Name')? Würden Sie Namen für beide bekommen?
MoDrags

Etwa so: Model.findOne ({_ id: 'foo'}). Populate ({Pfad: 'Elternmodell', populate: {Pfad: 'someProperty', populate: {Pfad: 'somePropertyBelow'}})
dontmentionthebackup

28

Versuchen Sie dies:

User.find(options, '_id user email facebook').populate('facebook', '_id pos').exec(function (err, users) {

24

Versuchen Sie dies:

applicantListToExport: function (query, callback) {
  this
   .find(query).select({'advtId': 0})
   .populate({
      path: 'influId',
      model: 'influencer',
      select: { '_id': 1,'user':1},
      populate: {
        path: 'userid',
        model: 'User'
      }
   })
 .populate('campaignId',{'campaignTitle':1})
 .exec(callback);
}

Nur um ein wenig zu erklären, was hier passiert: Hiermit werden Felder in einer verschachtelten und in einer einfachen Auffüllung ausgewählt.
Andre Simon

Du hast meinen Tag gerettet :)
Peshraw H. Ahmed


3

Sie versuchen:

Post.find({_id: {$nin: [info._id]}, tags: {$in: info.tags}}).sort({_id:-1})
.populate('uid','nm')
.populate('tags','nm')
.limit(20).exec();

2

Um die obigen Antworten zu ergänzen , können Sie Folgendes tun , wenn Sie alles einschließen, aber nur bestimmte Attribute ausschließen möchten :

.populate('users', {password: 0, preferences: 0})

0

Hallo für mich, es hat bei mir funktioniert. Ich habe das Benutzerfeld mit dem Auffüllcode ausgefüllt: --->

async function displayMessage(req,res,next){
    try{
        let data= await Msg.find().populate("user","userName userProfileImg","User")
               if(data===null) throw "Data couldn ot be loaded server error"
        else {
            res.status(200).json(data)
        }
    }   catch(err){
            next(err)
    }
}

Ich bekomme direkt das Ergebnis. Hier sind die Felder userName, userProfile image diejenigen, die selektiv benötigt werden, und die Syntax für das Auffüllen lautet: ->

 .populate("user field to populate","fields to display with spaces between each of them " , "modelName ")

Jeder Parameter sollte in Anführungszeichen stehen.

Unten ist die Ausgabe, die ich erhalte. Eine weitere Sache, die Sie nicht über die aufgefüllte Unterdokument-ID sorgen müssen, erhalten Sie automatisch.

[
    {
        "_id": "5e8bff324beaaa04701f3bb9",
        "text": "testing message route",
        "user": {
            "_id": "5e8bf062d3c310054cf9f293",
            "userName": "boss",
            "userProfileImg": "img"
        },
        "__v": 0
    },
    {
        "_id": "5e8bff8dd4368a2858e8f771",
        "text": "testing message route second",
        "user": {
            "_id": "5e8bf062d3c310054cf9f293",
            "userName": "boss",
            "userProfileImg": "img"
        },
        "__v": 0
    },
    {
        "_id": "5e8c0c08e9bdb8209829176a",
        "text": "testing message route second",
        "user": {
            "_id": "5e8bf062d3c310054cf9f293",
            "userName": "boss",
            "userProfileImg": "img"
        },
        "__v": 0
    },
    {
        "_id": "5e8c0e0bcb63b12ec875962a",
        "text": "testing message route fourth time",
        "user": {
            "_id": "5e8bf062d3c310054cf9f293",
            "userName": "boss",
            "userProfileImg": "img"
        },
        "__v": 0
    }
]

0

In der folgenden Abfrage habe ich Artikel abgerufen, die der Bedingung entsprechen, dass show=truedie abgerufenen Daten title and createdAt auch die Kategorie des Artikels abrufen, nur den Titel der Kategorie und seine ID.

let articles = await articleModel
        .find({ show: true }, { title: 1, createdAt: 1 })
        .populate("category", { title: 1, _id: 1 });

-1

Sie können versuchen, unten zu verwenden,

 Model
    .find()
    .populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
    ...
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.