简体   繁体   中英

Get related items in keystone

Working on a project in KeystoneJS and I'm having trouble figuring out the mongoose relationship bit.

According to the keystone docs, let's say we have the following models: User and Post . Now a post has a relationship to a user, so I'll write:

Post.add({
    author: { type: Types.Relationship, ref: 'User' }
});

and then:

User.relationship({ path: 'posts', ref: 'Post', refPath: 'author' });

Now, I want to be able to see all posts related to that User without having to query for both a User and Posts. For example, if I queried for a user object I would like to be able to do user.posts and have access to those related posts. Can you do this with mongoose/keystone?

As far as I understand, keystone's List Relationship has nothing to do with mongoose and querying. Instead, it is used by keystone's admin UI to build out the relationship queries before rendering them in the view. This said I would forget User.relationship(...); solving your problem, although you want it for what I just mentioned.

The following should work fine based on your schema, but only populates the relationship on the one side:

var keystone = require('keystone');
keystone.list('Post').model.findOne().populate('author', function (err, doc) {
  console.log(doc.author.name); // Joe
  console.log(doc.populated('author'));  // '1234af9876b024c680d111a1' -> _id
});

You could also try this the other way, however...

keystone.list('User').model.findOne().populate('posts', function (err, doc) {
  doc.posts.forEach(function (post) {
    console.log(post);
  });
});

...mongoose expects that this definition is added to the Schema . This relationship is added by including this line in your User list file:

User.schema.add({ posts: { type: Types.Relationship, ref: 'Post', many: true } })

After reading the keystone docs, this seems to be logically equivalent the mongoose pure way, User.schema.add({ posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }] }); . And now you are now maintaining the relationship on both lists. Instead, you may want to add a method to your keystone list.

User.schema.methods.posts = function(done){
  return keystone.list('Post').model.find()
    .where('author', this.id )
    .exec(done);
};

By adding a method to your User list, it saves you from persisting the array of ObjectId s relating the MongoDB document back to the Post documents. I know this requires a second query, but one of these two options look to be your best bet.

I found this on their github https://github.com/Automattic/mongoose/issues/1888 , check it for context, but basically says to use the keystone populateRelated() method. I tested it and does work

// if you've got a single document you want to populate a relationship on, it's neater
Category.model.findOne().exec(function(err, category) {
  category.populateRelated('posts', function(err) {
    // posts is populated
  });
});

I'm aware the question is old but this has to be out there for further reference

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