Reputation: 293
Example
I have two collections, one for Posts and one for Labels that look like this:
Post {
"_id": "WZTEGgknysdfXcQBi",
"title": "ASD",
"labels": {},
"author": "TMviRL8otm3ZsddSt",
"createdAt": "2016-01-14T08:42:42.343Z",
"date": "2016-01-14T08:42:42.343Z"
}
Label {
"_id": "9NCNPGH8F5MWNzjkA",
"color": "#333",
"name": "Grey Label",
"author": "TMviRL8otm3ZsddSt"
}
What I want to achieve is to have Posts with multiple Labels.
Problem is I cannot insert label data into the post. I have a template to add new post and in there I am repeating over the labels. Then in the helpers I check which label is checked and store it into an array, but I cannot insert that array in the Posts collection.
'submit .add-entry': function(event) {
var title = event.target.title.value;
var description = event.target.description.value;
var checkedLabels = $('.label-checkbox:checked');
//initiate empty array
var labelsArray = [];
//go over the checked labels
for(i = 0; i < checkedLabels.length; i++){
var label = checkedLabels[i].value;
// store ids into array
labelsArray.push(label)
};
Posts.insert({
title: title,
description: description,
labels: labelsArray
});
Q1: Should I insert all the tags data or only the ID fetch more details from the Tags collection based on that ID?
Q2: How can I insert that array of labels into a Post? The code above does not work because it needs an Object
Q3 What is the best way to achieve such relationship between collections?
Upvotes: 0
Views: 260
Reputation: 20838
Q1: Should I insert all the tags data or only the ID fetch more details from the Tags collection based on that ID?
It depends: does the label change? If it mutable, then storing the ID only is best so that fetching the Label by ID will always return the proper data. Otherwise you need to update every Post with the new label info.
Q2: How can I insert that array of labels into a Post? The code above does not work because it needs an Object
If the code does not work, it is likely that you are using some sort of schema that is not matched: to insert an array in place of an object, you need to modify the schema to accept an Array. You did not post details of a schema.
Q3 What is the best way to achieve such relationship between collections?
You should look at 'denormalization': this is the term used for this type of things in a NoSQL database like MongoDB. There is no straight answer, it depends on the relationship (1-1, 1-many, many-1) and the ratio of each 'many': in some cases it is best to nest data into objects if they are immutable or if dealing with updates is not too much of a pain.
this series of blog posts should help you get a better understanding: http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1
Upvotes: 1
Reputation: 1424
(Q1) You can insert all tag IDs to that labels
list and keep that updated (Q3) I think that's a good practice; in your development process try to publish using composite collections with this package: https://github.com/englue/meteor-publish-composite
(Q2) Inserting is easy:
Post.insert({title:'Abc', labels:['one', 'two']});
You would need to use $addToSet
to update. Here's an example of a possible method:
let setModifier = {
$addToSet: {
labels: myArrayOfLabelIDs
}
};
return Post.update({
_id: id
}, setModifier);
Note: Never use inserts on the client (like you did). My example can be added as a method on the server (use check()
inside that) and can be called from the client upon submit like:
Meteor.call('myMethod', id, labelsArray)
Upvotes: 1