简体   繁体   中英

Mongoose populate ObjectID from multiple possible collections

I have a mongoose model that looks something like this

var LogSchema = new Schema({
    item: {
        type: ObjectId,
        ref: 'article',
        index:true,
    },
});

But 'item' could be referenced from multiple collections. Is it possible to do something like this?

var LogSchema = new Schema({
    item: {
        type: ObjectId,
        ref: ['article','image'],
        index:true,
    },
});

The idea being that 'item' could be a document from the 'article' collection OR the 'image' collection.

Is this possible or do i need to manually populate?

Question is old, but maybe someone else still looks for similar issues :)

I found in Mongoose Github issues this:

mongoose 4.x supports using refPath instead of ref:

var schema = new Schema({
  name:String,
  others: [{ value: {type:mongoose.Types.ObjectId, refPath: 'others.kind' } }, kind: String }]
})

In @CadeEmbery case it would be:

var logSchema = new Schema({
  item: {type: mongoose.Types.ObjectId, refPath: 'kind' } },
  kind: String
})

But I did't try it yet...

First of all some basics

The ref option says mongoose which collection to get data for when you use populate() .

The ref option is not mandatory , when you do not set it up, populate() require you to give dynamically a ref to him using the model option.

@example

 populate({ path: 'conversation', model: Conversation }).

Here you say to mongoose that the collection behind the ObjectId is Conversation .

It is not possible to gives populate or Schema an array of refs .

Some others Stackoverflow people asked about it.


Soluce 1: Populate both (Manual)

Try to populate one, if you have no data, populate the second.


Soluce 2: Change your schema

Create two link, and set one of them.

var LogSchema = new Schema({
    itemLink1: {
        type: ObjectId,
        ref: 'image',
        index: true,
    },
    itemLink2: {
        type: ObjectId,
        ref: 'article',
        index: true,
    },
});


LogSchema.find({})
     .populate('itemLink1')
     .populate('itemLink2')
     .exec()

Dynamic References via refPath

Mongoose can also populate from multiple collections based on the value of a property in the document. Let's say you're building a schema for storing comments. A user may comment on either a blog post or a product.

  body: { type: String, required: true },
  on: {
    type: Schema.Types.ObjectId,
    required: true,
    // Instead of a hardcoded model name in `ref`, `refPath` means Mongoose
    // will look at the `onModel` property to find the right model.
    refPath: 'onModel'
  },
  onModel: {
    type: String,
    required: true,
    enum: ['BlogPost', 'Product']
  }
});

const Product = mongoose.model('Product', new Schema({ name: String }));
const BlogPost = mongoose.model('BlogPost', new Schema({ title: String }));
const Comment = mongoose.model('Comment', commentSchema);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM