question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bi-directional Many-to-many relationships using virtuals

See original GitHub issue

Hi guys,

Thanks for adding the virtual population, it’s saved a lot of time! I still have an issue with the many-to-many. I want to be able to use “classics relationships” and virtuals as well.

// Populate
const User = new Schema({
  name: String,
  articles: [{ type: Schema.Types.ObjectId, ref: 'Article' }]
});

const Article = new Schema({
  title: String,
  authors: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});

const article = new Articles({ title: 'My post', authors: ['1234', '5678'] }); 
article.save((err, article) => {...});

Article.find({}).populate('authors') .exec((err, articles) => {...}); // Work fine, with populated values

User.find({}).populate('articles') .exec((err, articles) => {...});  // Normal behavior, the articles attributes is an empty array.

With the new virtual population, I was trying to make something to not have to maintain the consistency between my many-to-many relationships. I would be able to create an article or user and spent some user’s ID or article’s ID when I create them and didn’t have to think about the relationships direction. I tried this below but it does not work.

// Populate + virtuals
const User = new Schema({
  name: String,
  articles: [{ type: Schema.Types.ObjectId, ref: 'Article' }]
});

const Article = new Schema({
  title: String,
  authors: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});

// Try to also apply virtual on existing relationships attributes
User.virtual('articles', {
  ref: 'Article',
  localField: '_id',
  foreignField: 'authors'
});

Article.virtual('authors', {
  ref: 'User',
  localField: '_id',
  foreignField: 'articles'
});

const user1 = new User({ name: 'John Doe' }) // _id = 1234
const user2 = new User({ name: 'Mickey Mouse' }) // _id = 5678 

const article = new Articles({ title: 'My post', authors: ['1234', '5678'] }); 
article.save((err, article) => {...});

Article.find({}).populate('authors') .exec((err, articles) => {...}); // Work fine, with populated values

User.find({}).populate('articles') .exec((err, articles) => {...}); // I would also get the articles thanks to the virtual population

Any solution to do that?

Thanks 😃

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7

github_iconTop GitHub Comments

12reactions
vkarpov15commented, Aug 6, 2016

Hmm I’d imagine the issue is due to the fact that you have a virtual field with the same name as a real field. That’s not a good idea. If you want to model this sort of many-to-many, I’d recommend having putting the array on the smaller side of the many-to-many and using a virtual for the other side:

// Populate + virtuals
const User = new Schema({
  name: String
});

// Since an article will likely not have hundreds of authors but an author may have hundreds of articles
const Article = new Schema({
  title: String,
  authors: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});

// Try to also apply virtual on existing relationships attributes
User.virtual('articles', {
  ref: 'Article',
  localField: '_id',
  foreignField: 'authors'
});

// Now you should be able to do User.find().populate('articles') and Article.find().populate('authors')
6reactions
ckee83commented, Mar 13, 2017

In the above example is it required to .push authors into the Article collection before it will be returned in a populate?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Bi-directional, many-to-many and virtual relationships in ...
Mark explains different types of relationships in Power BI data models - in particular bi-directional, many-to-many and virtual ...
Read more >
Different options to model many-to-many relationships ... - SQLBI
There are two options to model many-to-many relationships using Tabular and Power BI: you can use either a regular bidirectional filter ...
Read more >
Java persistence with JPA and Hibernate, Part 2: Many-to ...
In JPA we use the @ManyToMany annotation to model many-to-many relationships. This type of relationship can be unidirectional or bidirectional:.
Read more >
Model relationships in Power BI Desktop - Microsoft Learn
A model relationship propagates filters applied on the column of one model table to a different model table. Filters will propagate so long...
Read more >
Hibernate Tips: How to map a bidirectional many-to-many ...
You need to model the association on both entities if you want to be able to navigate it in both directions. Let's have...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found