Поверніть певні поля з .populate () з Mongoose


86

Після запуску запиту я отримую значення JSON від MongoDB. Проблема в тому, що я не хочу повертати всі JSON, пов’язані з моїм поверненням, я спробував шукати документи і не знайшов належного способу зробити це. Мені було цікаво, що, якщо це можливо, і якщо так, який правильний спосіб зробити це. Приклад: У БД

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

Яким буде правильний спосіб повернення поля, якщо воно існує для користувача, але якщо воно не повертає іншого поля. Для прикладу вище я хотів би повернути [email][address]поле для RMS та [facebook][address]поле для Цукербурга. Це те, що я намагався знайти, якщо поле є нульовим, але, схоже, воно не працює.

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

Відповіді:


90

Я не зовсім зрозумів, що ви маєте на увазі під "поверненням поля", але ви можете використовувати lean()запит, щоб ви могли вільно модифікувати вихідні дані, а потім заповнити обидва поля та обробити результат, щоб зберегти лише те поле, яке ви хочете:

.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
це не працює для мене, хтось знає, чи це змінилося з оновленням Mongoose?
кодування ніндзя

1
Це не працює для мене теж, я намагався .populate('model', 'field'), .populate('model', { field: 1}), .populate('model', [field])з і без lean()і з і без selectPopulatedPaths: falseна моделі , але у мене завжди повний заповнений об'єкт у відповідь. У документації сказано, що ваша відповідь має бути правильною, але я не можу змусити її працювати. Хтось має таку ж проблему?
mel-mouk

54

Якщо ви хочете, щоб для заповнених документів було повернуто лише кілька конкретних полів, це можна зробити, передавши синтаксис імені поля як другий аргумент методу заповнення.

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

Див. Вибір поля заповнення мангуста


8
Працює нормально. Ви також можете повернути більше полів, лише ви повинні передати більше полів. -> заповнити ('the_field_to_populate', 'ім'я прізвище')
slorenzo

Що робити, якщо у вас було більше однієї моделі для заповнення і ви хотіли б поля для них? Подобається заповнювати ('дописи користувачів', 'ім'я')? Чи отримаєте ви імена для обох?
MoDrags 21.03.17

Щось подібне: Model.findOne ({_ id: 'foo'}). Populate ({path: 'parent-model', populate: {path: 'someProperty', populate: {path: 'somePropertyBelow'}}})
dontmentionthebackup

28

Спробуйте зробити це:

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

26

Спробуйте зробити це:

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
Тільки для того, щоб трохи пояснити, що тут відбувається: це виділення полів у вкладеному та простому заповненні.
Андре Саймон

Ти врятував мій день :)
Пешров Х. Ахмед


4

вам спробувати:

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

2

Щоб доповнити відповіді вище, якщо ви хочете включити все, але виключити лише певні атрибути , ви можете зробити наступне:

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

0

Привіт, для мене це спрацювало. Я заповнив поле користувача, використовуючи код заповнення: --->

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

я безпосередньо отримую результат. Тут поля userName, imageProfile image - це ті, які мені потрібні вибірково, а синтаксис для заповнення: ->

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

кожен параметр повинен бути в перевернутій комі.

Нижче наведено вихідні дані, які я отримую. Ще одна річ, про яку вам не доведеться турбуватися про заповнення ідентифікатора піддокументу, і ви автоматично отримаєте їх.

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

У наступному запиті я отримав статті, які відповідають умові, show=trueотримані дані title and createdAt також отримують категорію статті лише заголовок категорії та її ідентифікатор.

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

-1

ви можете спробувати скористатися нижче,

 Model
    .find()
    .populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
    ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.