Statt dessen, was Sie versuchen zu tun, sollten Sie "Diskriminatoren" verwenden, was in der Tat der richtige Weg ist, eine Beziehung zu handhaben, bei der die Objekttypen in der angegebenen Referenz variieren.
Sie verwenden Scheidern durch die unterschiedliche Art und Weise, in der Sie das Modell definieren, die anstelle von einem „Basismodell“ konstruiert und Schema wie in:
const contentSchema = new Schema({
name: String
});
const articleSchema = new Schema({
image: String,
});
const eventSchema = new Schema({
image: { type: Schema.Types.ObjectId, ref: 'Medium' }
});
const cardSchema = new Schema({
name: String,
data: { type: Schema.Types.ObjectId, ref: 'Content' }
});
const Medium = mongoose.model('Medium', mediumSchema);
const Card = mongoose.model('Card', cardSchema)
const Content = mongoose.model('Content', contentSchema);
const Article = Content.discriminator('Article', articleSchema);
const Event = Content.discriminator('Event', eventSchema);
Anstatt also Sie ein „Basismodell“ definieren, wie Content
hier, worauf Sie die Referenzen tatsächlich zeigen innerhalb Event
. Der nächste Teil besteht darin, dass das abweichende Schema für dieses Modell tatsächlich über die .discriminator()
-Methode aus dem Basismodell registriert wird, im Gegensatz zur .model()
-Methode. Dadurch wird das Schema mit dem allgemeinen Modell Content
so registriert, dass beim Angeben einer mit .discriminator()
definierten Modellinstanz unter Verwendung des registrierten Modellnamens ein spezielles Feld __t
in diesen Daten enthalten ist.
Abgesehen von Mungo zu .populate()
auf verschiedenen Typen zu aktivieren, hat dies auch den Vorteil, ein "vollständiges Schema" zu den verschiedenen Arten von Elementen. Sie haben also verschiedene Validierungsmethoden und andere Methoden, wenn Sie möchten. Es ist in der Tat "Polymorphismus" bei der Arbeit in einem Datenbankkontext, mit hilfreichen Schema-Objekten beigefügt.
Daher können wir sowohl die verschiedenen "Joins" demonstrieren, die ausgeführt werden, als auch, dass Sie jetzt die einzelnen Modelle für Article
und Event
verwenden können, die nur die Elemente in allen Abfragen und Operationen behandeln würden. Und nicht nur können Sie "einzeln" verwenden, aber da der Mechanismus dafür die Daten in der gleichen Sammlung speichert, gibt es auch ein Content
Modell, das Zugang zu diesen beiden Typen gibt. Das ist im Wesentlichen, wie die Hauptbeziehung in der Definition zum Event
Schema funktioniert.
Als vollständige Liste
const async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.set('debug',true);
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/cards');
const mediumSchema = new Schema({
title: String
});
const contentSchema = new Schema({
name: String
});
const articleSchema = new Schema({
image: String,
});
const eventSchema = new Schema({
image: { type: Schema.Types.ObjectId, ref: 'Medium' }
});
const cardSchema = new Schema({
name: String,
data: { type: Schema.Types.ObjectId, ref: 'Content' }
});
const Medium = mongoose.model('Medium', mediumSchema);
const Card = mongoose.model('Card', cardSchema)
const Content = mongoose.model('Content', contentSchema);
const Article = Content.discriminator('Article', articleSchema);
const Event = Content.discriminator('Event', eventSchema);
function log(data) {
console.log(JSON.stringify(data, undefined, 2))
}
async.series(
[
// Clean data
(callback) =>
async.each(mongoose.models,(model,callback) =>
model.remove({},callback),callback),
// Insert some data
(callback) =>
async.waterfall(
[
(callback) =>
Medium.create({ title: 'An Image' },callback),
(medium,callback) =>
Content.create(
[
{ name: "An Event", image: medium, __t: 'Event' },
{ name: "An Article", image: "A String", __t: 'Article' }
],
callback
),
(content,callback) =>
Card.create(
[
{ name: 'Card 1', data: content[0] },
{ name: 'Card 2', data: content[1] }
],
callback
)
],
callback
),
// Query and populate
(callback) =>
Card.find()
.populate({
path: 'data',
populate: [{
path: 'image'
}]
})
.exec((err,cards) => {
if (err) callback(err);
log(cards);
callback();
}),
// Query on the model for the discriminator
(callback) =>
Article.findOne({},(err,article) => {
if (err) callback(err);
log(article);
callback();
}),
// Query on the general Content model
(callback) =>
Content.find({},(err,contents) => {
if (err) callback(err);
log(contents);
callback();
}),
],
(err) => {
if (err) throw err;
mongoose.disconnect();
}
);
Und der Beispielausgabe für verschiedene Abfragen
Mongoose: cards.find({}, { fields: {} })
Mongoose: contents.find({ _id: { '$in': [ ObjectId("595ef117175f6850dcf657d7"), ObjectId("595ef117175f6850dcf657d6") ] } }, { fields: {} })
Mongoose: media.find({ _id: { '$in': [ ObjectId("595ef117175f6850dcf657d5") ] } }, { fields: {} })
[
{
"_id": "595ef117175f6850dcf657d9",
"name": "Card 2",
"data": {
"_id": "595ef117175f6850dcf657d7",
"name": "An Article",
"image": "A String",
"__v": 0,
"__t": "Article"
},
"__v": 0
},
{
"_id": "595ef117175f6850dcf657d8",
"name": "Card 1",
"data": {
"_id": "595ef117175f6850dcf657d6",
"name": "An Event",
"image": {
"_id": "595ef117175f6850dcf657d5",
"title": "An Image",
"__v": 0
},
"__v": 0,
"__t": "Event"
},
"__v": 0
}
]
Mongoose: contents.findOne({ __t: 'Article' }, { fields: {} })
{
"_id": "595ef117175f6850dcf657d7",
"name": "An Article",
"image": "A String",
"__v": 0,
"__t": "Article"
}
Mongoose: contents.find({}, { fields: {} })
[
{
"_id": "595ef117175f6850dcf657d6",
"name": "An Event",
"image": "595ef117175f6850dcf657d5",
"__v": 0,
"__t": "Event"
},
{
"_id": "595ef117175f6850dcf657d7",
"name": "An Article",
"image": "A String",
"__v": 0,
"__t": "Article"
}
]
Gibt es etwas in der mitgelieferten Antwort, die Sie glaubt nicht, Ihre Frage zu beantworten? Wenn ja, dann kommentieren Sie bitte die Antwort, um zu klären, was genau adressiert werden muss, was nicht der Fall ist. Wenn es tatsächlich die Frage beantwortet, die Sie gestellt haben, dann beachten Sie bitte [Akzeptieren Sie Ihre Antworten] (https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) zu den Fragen, die Sie haben fragen Sie –
"Bump". Noch keine Antwort? –