简体   繁体   中英

Creating a many-to-many relationship between 2 mongodb collections by ids

I have two collections. One is called Posts and the other is called Categories . In the posts collection, are individual posts that each contain an array of id's called categories which are id's of the categories the individual post belongs to stored in the posts.

在此处输入图片说明

The second collection is the Categories collection which contains the categories each of the posts belong to

在此处输入图片说明

Goal

In my template, I am displaying each post as its title, content, image and author as well as the Category names which come about by linking the Category Ids in the Posts collection to the individual categories in the Category collection

<template name="latest">
    {{#each posts}}
<div>{{> category}}</div>
      <h5 class="latest-title">{{title.rendered}}</h5>
  <img class="latest-img" src="{{featured_image_thumbnail_url}}" alt="" />
    {{/each}}
</template>

In my category template

<template name="category">
  {{#each categories}}
 {{name}}
  {{/each}}

</template>

In my category.js

Template.category.helpers({
  categories(){
    return CategoryCollection.find({ id: parseInt(this.categories) });
  }
});

As you can see, I want to display the names of the categories belonging to a post, they are in an array because a post might have 3 categories it belongs too. but I can't seem to get it to work.

Edit

This is my edit to include the $in

Template.category.helpers({
  categories(){
    return CategoryCollection.find({ id: {$in: this.categories }});
  }
});

And this is my template

<template name="category">
  {{#each categories}}
  {{name}}
  {{/each}}

</template>

It doesn't seem to be working.

Progress

It wasn't working because I hadn't assigned categories to my example post, the above edited code is the answer

Another solution I'm using for this kind of stuff is just showing the categories in the array of that post, without even a helper. Here is what I do...

Inside the method:

//the categories is what you pass from the client as an array of strings
//IE: ['cat1', 'cat2']

categories.forEach(function(cc){
    const cat = Categories.findOne({name: cc});
    if(!cat){
        Categories.insert({
            name: cc,
            count: 1
        });
    } else {
        //increment count if it exists
        Categories.update({name: cc}, {
            $inc:{
                count: 1
            }
        });
    }
});

The reason I insert with count 1 and increment the count if category exists is for multiple different use cases such as:

  1. Showing existing categories on search so that it always returns existing documents

  2. In case of edit/delete post, if count == 1 , delete the category if count > 1 , decrement count of that category.

  3. Showing a reference of existing categories when a user is adding/editing posts. Depending on what they write on the input I return Category recommendations with a regex.

In the post, just show the category names from the post. No need to find category.

<!-- 
    see that its {{this}} not {{name}} because 
    we saved the categories to the post as an array of strings 
    we'd do {{name}} if we were looping through the categories collection
-->
{{#each categories}}
    {{this}}
{{/each}}

If you need to access the category from the DB in the post like click events, you can do a quick Categories.findOne({name: this.name})

I see that you save other stuff to the Category collection which I'd probably save to the post itself and some, I wouldn't even save and generate the necessary stuff client side if they're like links etc.

您要使用$in运算符:

 return CategoryCollection.find({ id: {$in: this.categories }});

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