Сложное создание отношений "многие ко многим" между 3 коллекциями.

У меня есть 3 коллекции: meteor.user(), Categories и Posts.

Пользователь может выбрать подписку на сообщения любой категории, сохранив идентификатор категории в массиве в meteor.user()

Конечная цель этого состоит в том, чтобы у пользователя был личный поток, в котором показывались только сообщения в тех категориях, за которыми он следит.

Каждая публикация в Posts collection содержит массив категорий, в которых она представлена.

введите здесь описание изображения

и каждая категория содержит в себе массив сообщений, каждое сообщение в массиве имеет поле ID сообщения.

введите здесь описание изображения

Где id: 67 - это идентификатор категории, а posts.ID: 74 - это идентификатор сообщения в категории.

ниже - идентификатор сообщения в коллекции сообщений с совпадениями posts.ID в коллекции категорий

введите здесь описание изображения

Пользователь сохраняет идентификатор категории, чтобы он отображался как массив категорий в meteor.user ()

введите здесь описание изображения

Когда я это сделаю

Template.userTimeline.helpers({
  category: function() {
    var posts = Category.find({
      id: {
        $in: Meteor.user().category
      }
    });
    return posts
    console.log(posts);
  }
});

я могу сделать это

 {{#each category}}
  <ul class="article-timeline">
    {{#each posts}} {{ID}} {{/each}}
  </ul>
{{/each}}

Но это позволяет мне получить доступ к posts.ID в коллекции категорий и отобразить его.

ПРОБЛЕМА

Как я могу пойти дальше и сопоставить сообщения. ID, который я получил с помощью приведенного выше кода, с идентификатором сообщения в Post, чтобы я мог получить доступ к сообщениям из коллекции Posts. Могу я сделать что-нибудь подобное?

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);
  }
});

ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ ПОСЛЕ ОТВЕТА ЗИМА

Итак, решение, которое вы мне дали, берет post.title из объекта сообщения, содержащегося в моей Categories коллекции, как показано ниже.

введите здесь описание изображения

Этот post массив в Category collection является неполным, это копия оригинального Posts Collection

мне нужно использовать post.ID, как показано на изображении выше. т.е. массив сообщений в Коллекции категорий, чтобы создать связь многие ко многим с id сообщения в исходной Коллекции Posts, поэтому вместо post.title мне нужно иметь title.rendered, как показано ниже.

Сборник сообщений.

введите здесь описание изображения

Если вы видите, что ID (не верхний идентификатор, который является идентификатором категории), post.ID в массиве сообщений в коллекции "Категории" является ИДЕНТИЧНЫМ по отношению к id сообщения в коллекции Posts. Это суть всего, помогите мне создать отношения, чтобы вместо отображения title или post.title из массива сообщений внутри Коллекции Categories мне нужно было отображать title.rendered в исходной Коллекции Posts.


person Shingai Munyuki    schedule 02.06.2017    source источник
comment
Я смиренно предлагаю вам поместить всю схему в разные коллекции. Все данные будут доступны на стороне клиента, что очень опасно. Вы скорее создаете соответствующие коллекции, а затем создадите общее поле для сопоставления каждой записи. Вам действительно не нужно усложнять вещи, поскольку внутренние отношения могут работать следующим образом: ›stackoverflow.com/questions/44203584/ Вы можете просто зацикливать данные внутри шаблонов с помощью помощники и подписки.   -  person Ankur Soni    schedule 02.06.2017
comment
Привет, спасибо за ответ. @AnkurSoni Это сложно, я не определил схему, данные поступают через json в виде сообщения от WordPress. Поймите, почему я иду на это.   -  person Shingai Munyuki    schedule 02.06.2017
comment
какой у Вас вопрос? :)   -  person Ankur Soni    schedule 02.06.2017
comment
Вместо отображения posts.ID в шаблоне, как я могу сопоставить posts.ID в коллекции категорий с его точным соответствием в сообщениях, который является идентификатором сообщения, чтобы вместо отображения данных сообщений из категории коллекции, я могу отображать данные из самого сообщения, сопоставляя идентификаторы @AnkurSoni   -  person Shingai Munyuki    schedule 02.06.2017
comment
Я уже давал вам ссылку. Загляни в ответ. Он объясняет все, о чем вы только что спросили. Сохраняйте спокойствие, расслабьтесь и прочтите ответ. У меня тоже когда-то был этот вопрос, решение очень простое.   -  person Ankur Soni    schedule 02.06.2017


Ответы (1)


похоже, что вы не контролируете формат данных, поэтому вам придется использовать вложенный цикл, чтобы иметь дело с форматом, который у вас есть. Я думаю, что следующее должно работать.

Template.userTimeline.helpers({
  categories: function() {
    return Category.find({
      id: {
        $in: Meteor.user().category
      }
    });
  }
});

обратите внимание, я изменил имя вашего помощника.

{{#each category in categories}}
  {{category.description}}
  {{#each post in category.posts}}
    {{post.title}}
  {{/each}}
{{/each}}

c.f. http://blazejs.org/guide/spacebars.html#Each-in

РЕДАКТИРОВАТЬ:

в идеале вы могли бы выполнить соединение на стороне сервера, используя такой пакет, как https://atmospherejs.com/reywood/publish-composite

но поскольку у вас нет контроля над этим, вы можете выполнить соединение на стороне клиента. вы бы сделали это в 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
        }
    });
});

затем, просто изменив шаблон, вы можете получить эти фактические сообщения:

{{#each category in categories}}
  {{category.description}}
  {{#each post in category.actualPosts}}
    {{post.title}}
  {{/each}}
{{/each}}

выполнение соединений на стороне клиента немного сложнее, потому что, как написано выше, вам не хватает реакции на отслеживаемые категории пользователя и сообщения в существующих категориях. так что вы можете добавить все это в автозапуск. который будет отслеживать изменения в категории Meteor.user ()., но не уверен, будет ли это отслеживать изменения сообщений в категориях. но это должно помочь вам в этом.

ИЗМЕНИТЬ 2:

о да, если вы сделаете это таким образом, этот слушатель останется активным, когда шаблон исчезнет, ​​если вы не вызовете для него stop (). так...

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);
    });
});
person zim    schedule 02.06.2017
comment
Спасибо, что нашли время ответить. Пожалуйста, взгляните на дальнейшее редактирование, чтобы точно объяснить, что мне нужно. Короче говоря, я уже успешно получаю post.title, но проблема в том, что он исходит из массива сообщений в коллекции категорий, а не из коллекции сообщений. Пожалуйста, взгляните на правку для дальнейшего объяснения @zim - person Shingai Munyuki; 02.06.2017
comment
@ShingaiMunyuki, понял. Я обновлю свой ответ с помощью клиентского соединения. - person zim; 03.06.2017