mongodb-js / mongoose-autopopulate

Always populate() certain fields in your mongoose schemas
Apache License 2.0
221 stars 36 forks source link

Autopopulate reference if possible, otherwise return value #74

Closed BoKKeR closed 4 years ago

BoKKeR commented 4 years ago

I would want to use autopopulate based on the value field property.

If mongoose-autopopulate cant resolve the value reference, I would want to return the original value instead of returning null. Which is the result of not being able to resolve the reference.

  @prop({
    ref: TemplateFieldArrayValue,
    autopopulate: true,
    type: String,
  })
  value?: string | boolean | number | Ref<TemplateFieldArrayValue>

Is there any way to achieve this with the package? I tried using an option's function but I think the options only affect the initial query and dont give access to the result.

vkarpov15 commented 4 years ago

You can do this with custom getters. Just make sure to set the getters to toObject() either in your toObject() calls, or globally using mongoose.set('toObject', { getters: true }); mongoose.set('toJSON', { getters: true });

Below is an example:

'use strict';

const mongoose = require('mongoose');

mongoose.set('useFindAndModify', false);

const { Schema } = mongoose;

run().catch(err => console.log(err));

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  });

  await mongoose.connection.dropDatabase();

  const Child = mongoose.model('Child', Schema({ name: String }));
  const Parent = mongoose.model('Parent', Schema({
    child: {
      type: 'ObjectId',
      ref: 'Child',
      get: function(v, schemaType) {
        // If `null` and this path is populated, return the populated id
        if (v == null && this.populated(schemaType.path)) {
          return this.populated(schemaType.path);
        }
        return v;
      }
    }
  }));

  await Parent.create({ child: new mongoose.Types.ObjectId() });

  const doc = await Parent.findOne().populate('child').exec();

  console.log(doc.child); // 5f2b122c2825d62430a94350
  console.log(doc.toObject({ getters: true })); // { ..., child: 5f2b122c2825d62430a94350, ... }
}