Devuelve ciertos campos con .populate () de Mongoose


82

Recibo un valor JSON de MongoDB después de ejecutar mi consulta. El problema es que no quiero devolver todo el JSON asociado con mi devolución, intenté buscar en los documentos y no encontré una forma adecuada de hacerlo. Me preguntaba qué pasa si es posible y, de ser así, cuál es la forma correcta de hacerlo. Ejemplo: en la base de datos

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

¿Cuál sería la forma correcta de devolver un campo si existe para un usuario, pero si no devuelve otro campo? Para el ejemplo anterior, me gustaría devolver el [email][address]campo para RMS y el [facebook][address]campo para Zuckerburg. Esto es lo que he intentado encontrar si un campo es nulo, pero parece que no funciona.

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

Respuestas:


89

No tengo muy claro lo que quiere decir con "devolver un campo", pero puede usar una lean()consulta para poder modificar libremente la salida, luego completar ambos campos y procesar posteriormente el resultado para mantener solo el campo que desea:

.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
esto no funciona para mí, ¿alguien sabe si esto ha cambiado con una actualización de Mongoose?
Codificación Ninja

1
Esto no está funcionando para mí tampoco, he intentado .populate('model', 'field'), .populate('model', { field: 1}), .populate('model', [field])con y sin lean()y con y sin selectPopulatedPaths: falseel modelo, pero siempre me dieron el objeto poblada completa en la respuesta. La documentación dice que se supone que su respuesta es la correcta, pero no puedo hacer que funcione. ¿Alguien tiene el mismo problema?
mel-mouk

51

Si solo desea que se devuelvan algunos campos específicos para los documentos rellenados, puede hacerlo pasando la sintaxis del nombre del campo como segundo argumento del método rellenar.

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

Ver selección de campo poblado de mangosta


7
Funciona bien. También puede devolver más campos, solo que debe pasar más campos. -> populate ('the_field_to_populate', 'nombre apellido')
slorenzo

¿Qué pasaría si tuviera más de un modelo para completar y quisiera campos para esos? ¿Como poblar ('publicaciones de usuarios', 'nombre')? ¿Conseguirías nombres para ambos?
MoDrags

Algo como esto: Model.findOne ({_ id: 'foo'}). Populate ({path: 'parent-model', populate: {path: 'someProperty', populate: {path: 'somePropertyBelow'}}})
dontmentionthebackup

28

Intenta hacer esto:

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

24

Intenta hacer esto:

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

Solo para explicar un poco lo que está sucediendo aquí: esto es para seleccionar campos en un poblado anidado y en un poblado simple.
Andre Simon

Me salvaste el día :)
Peshraw H. Ahmed


3

que intente:

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

2

Solo para complementar las respuestas anteriores, si desea incluir todo pero solo excluir ciertos atributos , puede hacer lo siguiente:

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

0

Hola para mí, funcionó para mí, completé el campo de usuario usando el código de llenado: --->

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

obtengo directamente el resultado. Aquí los campos userName, userProfile image son los que he requerido de forma selectiva y la sintaxis para rellenar es: ->

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

cada parámetro debe estar entre comas invertidas.

A continuación se muestra el resultado que recibo. Una cosa más que no tiene que preocuparse por la identificación del subdocumento de llenado, los obtendrá automáticamente.

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

En la siguiente consulta, recuperé artículos que coinciden con la condición, show=truelos datos title and createdAt recuperados también recuperan la categoría del artículo solo el título de la categoría y su identificación.

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

-1

puedes probar a usar a continuación,

 Model
    .find()
    .populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
    ...
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.