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: "[email protected]"
    },
    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");
      }
    }
  }
Schlafentzogener Bulbasaur
quelle

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;
    }
  });
JohnnyHK
quelle
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

dontmentionthebackup
quelle
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) {
scuencag
quelle
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);
}
S Kumar
quelle
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
21

Was Sie jetzt tun können, ist:

  .populate('friends', { username: 1, age: 1})
Scaraux
quelle
Du hast meinen Tag gerettet
Thamaraiselvam
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();
Tran Hoang Hiep
quelle
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})
Prashant Ghimire
quelle
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
    }
]
Pankaj Shukla
quelle
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 });
Ahmed Mahmoud
quelle
-1

Sie können versuchen, unten zu verwenden,

 Model
    .find()
    .populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
    ...
Naresh Ramoliya
quelle