[英]Creating a many to many relationship in a complex manner between 3 collections
I have 3 collections, meteor.user()
, Categories
and Posts
. 我有3个收藏集, meteor.user()
, Categories
和Posts
。
A user can choose to follow any category's posts by saving the id of the category in an array in meteor.user()
用户可以通过将类别的ID保存在meteor.user()
中的数组中来选择关注任何类别的帖子。
The end goal of this is that the user has a Personal stream where only the posts in the categories they are are following show up. 最终目的是使用户拥有一个“个人”流,其中仅显示他们正在关注的类别中的帖子。
Each post inside the Posts collection
has within it an array of the Categories it's featured in. Posts collection
每个Posts collection
都包含一个以其为特色的Categories数组。
and each category has within it an array of posts, each post in the array has a field of ID
of the post. 并且每个类别中都有一个帖子数组,该数组中的每个帖子都有一个帖子ID
字段。
Where id: 67
is the id of the category, and posts.ID: 74
is the id of a post within the category. 其中id: 67
是类别的ID,而posts.ID: 74
是类别中的帖子的id。
below is the id of the post in Posts collection with matches posts.ID in the category collection 以下是帖子集合中帖子的ID,与类别集合中的匹配posts.ID
The User saves a category id so it appears as the category array in meteor.user() 用户保存类别ID,因此它在meteor.user()中显示为类别数组
When I do this 当我这样做时
Template.userTimeline.helpers({
category: function() {
var posts = Category.find({
id: {
$in: Meteor.user().category
}
});
return posts
console.log(posts);
}
});
I can do this 我可以做这个
{{#each category}}
<ul class="article-timeline">
{{#each posts}} {{ID}} {{/each}}
</ul>
{{/each}}
But this lets me access the posts.ID within the category collection and display it. 但这使我可以访问类别集合中的posts.ID并显示它。
How can I go further and match posts.ID I got with the above code, to the the id of a post in Post
so that I can access the posts from the Posts
collection. 如何进一步匹配上面代码获得的posts.ID与Post中Post
的ID,以便可以从Posts
集合中访问Posts
。 Could i do something like this? 我可以做这样的事情吗?
Template.userTimeline.helpers({
category: function() {
var postsInCategory = Category.find({
id: {
$in: Meteor.user().category
}
});
var postMatch = Post.find({
ID: {
$in: postsInCategory
}
});
return postMatch
console.log(postMatch);
}
});
So the solution you have given me is taking post.title
from the post object contained within my Categories
collection as shown below. 因此,您给我的解决方案是从我的Categories
集合中包含的post对象中获取post.title
,如下所示。
This post
array within the Category collection
is incomplete, its a copy of an original Posts Collection
Category collection
此post
数组不完整,它是原始Posts Collection
的副本
what I need to do is use post.ID
as shown in the image above. 我需要做的是使用上图所示的post.ID
ie the post array within the Categories Collection, to create a many to many relationship with the id
of a post within the original Posts
Collection so, instead of having post.title
I need to have title.rendered
as below. 即类别集合中的帖子数组,以与原始Posts
集合中的Posts
id
建立多对多关系 ,因此, post.title
具有post.title
我还需要具有title.rendered
,如下所示。
Posts Collection. 帖子集合。
If you see that the ID
(not the top id, which is the id of the category), post.ID
in the post array within the Categories collection is IDENTICAL to the id
of the post in Posts
collection. 如果您发现该ID
(不是顶级的ID,这是该类别的ID), post.ID
类别集合中的后阵列中是相同的id
在后的Posts
集合。 This is the crux of it all, help me create a relationship so that, instead of displaying title
or post.title
from the post array within the Categories
Collection, I need to display title.rendered
within the original Posts
Collection. 这就是全部的症结所在,可以帮助我建立一种关系,这样,我需要在原始的Posts
集合中显示title.rendered
,而不是显示Categories
集合中的post数组中的title
或post.title
。
it sounds like you don't control the data format, so you would have to use a nested loop to deal with the format you have. 听起来好像您无法控制数据格式,所以您必须使用嵌套循环来处理您拥有的格式。 i think the following should work. 我认为以下应该工作。
Template.userTimeline.helpers({
categories: function() {
return Category.find({
id: {
$in: Meteor.user().category
}
});
}
});
note i changed the name of your helper. 请注意,我更改了您的助手的名称。
{{#each category in categories}}
{{category.description}}
{{#each post in category.posts}}
{{post.title}}
{{/each}}
{{/each}}
cf http://blazejs.org/guide/spacebars.html#Each-in cf http://blazejs.org/guide/spacebars.html#Each-in
EDIT: 编辑:
ideally, you would be able to do a server-side join using a package like https://atmospherejs.com/reywood/publish-composite 理想情况下,您将能够使用https://atmospherejs.com/reywood/publish-composite之类的程序包进行服务器端连接
but since you don't have control over that, you can do a client-side join. 但由于您对此无能为力,因此可以进行客户端加入。 you would do this in the onCreated() of your template (caveat: this is untested!) 您可以在模板的onCreated()中执行此操作(注意:这未经测试!)
this.subscribe('posts', function() {
let cursor = Categories.find({id: {$in: Meteor.user().category}});
cursor.observe({
added: function(newDocument) {
let category = newDocument;
// for this category, get all the associated post ids
let postIds = _.map(category.posts, function(p)) {
return p.ID;
};
// get the posts. we can fetch these because we waited for the publish of the posts collection.
let actualPosts = Posts.find({id: {$in: postIds}}).fetch();
// attach the actual posts to the category
category.actualPosts = actualPosts;
},
changed: function(newDocument, oldDocument) {
// if wanting to track changes to the categories, similar to added block
}
});
});
then with a simple change to the template, you can grab those actual posts: 然后只需对模板进行简单的更改,就可以获取这些实际的帖子:
{{#each category in categories}}
{{category.description}}
{{#each post in category.actualPosts}}
{{post.title}}
{{/each}}
{{/each}}
doing the client-side joins is a little more tricky, because as the above is written, you're missing reactivity to the user's tracked categories, and posts w/in the existing categories. 进行客户端联接比较棘手,因为撰写本文时,您缺少对用户跟踪类别的反应性,并且在现有类别中添加了帖子。 so you could further put all that in an autorun. 因此您可以将所有内容进一步放入自动运行中。 that would track changes to Meteor.user().category, but not sure if that would track post changes w/in the categories. 可以跟踪对Meteor.user()。category的更改,但不确定是否可以跟踪类别中的发布更改。 but this should get you a lot of the way there. 但这应该可以帮助您实现目标。
EDIT 2: 编辑2:
oh yeah, if you do it that way, that listener will stay active when the template goes away unless you call stop() on it. 哦,是的,如果这样做的话,除非您在模板上调用stop(),否则该侦听器将在模板消失时保持活动状态。 so... 所以...
Template.userTimeline.onDestroyed(function() {
let handle = this.observeHandle.get();
if (handle) {
handle.stop();
}
});
Template.userTimeline.onCreated(function() {
let self = this;
self.observeHandle = new ReactiveVar();
self.subscribe('posts', function() {
let cursor = Categories.find({id: {$in: Meteor.user().category}});
let handle = cursor.observe({
added: function(newDocument) {
let category = newDocument;
// for this category, get all the associated post ids
let postIds = _.map(category.posts, function(p)) {
return p.ID;
};
// get the posts
let actualPosts = Posts.find({id: {$in: postIds}}).fetch();
// attach the actual posts to the category
category.actualPosts = actualPosts;
},
changed: function(newDocument, oldDocument) {
// if wanting to track changes, similar to added block
}
});
self.observeHandle.set(handle);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.