Mongoose'dan .populate () ile belirli alanları döndür


86

Sorgumu çalıştırdıktan sonra MongoDB'den bir JSON değeri alıyorum. Sorun şu ki, iademle ilgili tüm JSON'u iade etmek istemiyorum, belgeleri aramayı denedim ve bunu yapmanın uygun bir yolunu bulamadım. Mümkünse ne olur ve eğer öyleyse bunu yapmanın doğru yolu nedir diye merak ediyordum. Örnek: DB'de

{
    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"
    }
} 

Bir kullanıcı için mevcutsa, ancak başka bir alan döndürmüyorsa, bir alanı geri döndürmenin uygun yolu nedir? Yukarıdaki örnek [email][address]için RMS [facebook][address]alanını ve Zuckerburg alanını döndürmek istiyorum . Bir alanın boş olup olmadığını bulmaya çalıştığım şey bu, ancak çalışıyor gibi görünmüyor.

 .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");
      }
    }
  }

Yanıtlar:


90

"Bir alanı döndürmek" ile ne demek istediğinizi tam olarak anlayamadım, ancak lean()çıktıyı özgürce değiştirebilmek için bir sorgu kullanabilir , ardından her iki alanı da doldurabilir ve yalnızca istediğiniz alanı korumak için sonucu son işlemden geçirebilirsiniz:

.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
bu benim için çalışmıyor, kimse bunun Mongoose güncellemesiyle değişip değişmediğini biliyor mu?
Ninja Coding

1
Bu Denedim, benim için de çalışmıyorsa .populate('model', 'field'), .populate('model', { field: 1}), .populate('model', [field])olan ve olmayan lean()ve olan ve olmayan selectPopulatedPaths: falsemodel üzerinde ama her zaman tepki olarak tam nüfuslu bir nesne var. Dokümantasyon, cevabınızın doğru cevap olması gerektiğini söylüyor, ancak işe yarayamam. Aynı sorunu yaşayan biri mi var?
mel-mouk

54

Doldurulan belgeler için yalnızca birkaç belirli alanın döndürülmesini istiyorsanız, bunu, alan adı sözdizimini populate yöntemine ikinci bağımsız değişken olarak ileterek gerçekleştirebilirsiniz.

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

Firavun faresi doldurma alanı seçimine bakın


8
İyi çalışıyor. Ayrıca daha fazla alan döndürebilirsiniz, yalnızca daha fazla alan geçmelisiniz. -> populate ('the_field_to_populate', 'name lastname')
slorenzo

Ya doldurmak için birden fazla modeliniz varsa ve bunlar için alanlar istiyorsanız? Doldurmak gibi ('kullanıcıların gönderileri', 'ad')? İkisine de isim verir misin?
MoDrags

Şuna benzer bir şey: Model.findOne ({_ id: 'foo'}). Doldurun ({yol: 'ebeveyn-model', doldurun: {yol: 'birProperty', doldurun: {yol: 'birPropertyBelow'}}})
dontmentionthebackup

28

Bunu yapmayı dene:

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

26

Bunu yapmayı dene:

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

1
Burada neler olduğunu biraz açıklamak gerekirse: Bu, iç içe geçmiş bir popülasyondaki ve basit bir popülasyondaki alanları seçmektir.
Andre Simon



4

denemek için:

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

2

Sadece yukarıdaki yanıtları tamamlamak için , her şeyi dahil etmek, ancak yalnızca belirli özellikleri hariç tutmak istiyorsanız, aşağıdakileri yapabilirsiniz:

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

0

Merhaba benim için benim için çalıştı, kullanıcı alanını doldurma kodunu kullanarak doldurdum: --->

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)
    }
}

doğrudan sonucu alıyorum. Burada userName, userProfile image alanları seçici olarak gerekli olan alanlardır ve doldurma sözdizimi şöyledir: ->

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

her parametre ters virgülle yazılmalıdır.

Aldığım çıktı aşağıdadır. Alt belge kimliğini doldurmak için endişelenmenize gerek olmayan bir şey daha bunları otomatik olarak alacaksınız.

[
    {
        "_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

Aşağıdaki sorguda, koşulla eşleşen makaleleri aldım show=true, alınan veriler title and createdAt ayrıca makale kategorisini yalnızca kategorinin başlığını ve kimliğini de alıyor.

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

-1

aşağıda kullanmayı deneyebilirsiniz,

 Model
    .find()
    .populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
    ...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.