How to implement a searchable joint table-view in meteor?


#1

Hi guys,

I kind of gave up an denormalization (Who would be interested in a denormalization-package for SimpleSchema & Collection 2?) and I am now searching for a SIMPLE and FAST way to implement a searchable joint table-view in meteor.

Basically I’d like to show a list of posts and give the user the option to search by the following:

  • search the post-text (field “text” in collection “Posts”)
  • search the comment-text (field “text” in collection “Comments”)
  • search the author-name (field “name” in collection “Author”)

Does anyone have experience with this kind of stuff? What packages/strategies can you recon?

This is the data-schema as an overview

This is how the UI is supposed to look like

This is how the collections are hooked up (using SimpleSchema)
Plus I also attached my current publication where I join the data for the client.

collections

export const Posts = new Mongo.Collection('posts')
export const Comments = new Mongo.Collection('comments')
export const Authors =  new Mongo.Collection('authors')

Authors.attachSchema(new SimpleSchema({
  author: {
    type: String,
  },
}))
Comments.attachSchema(new SimpleSchema({
  comment: {
    type: String,
  },
  postId: {
    type: String,
    optional: true,
  },
}))
Posts.attachSchema(new SimpleSchema({
  post: {
    type: String,
  },
  authorId: {
    type: String,
    optional: true,
  },
  commentIds: {
    type: [String],
    optional: true,
  },
}))

publication

// peerlibrary:meteor-reactive-publish
Meteor.publish('all-posts-with-comments-and-authors', function () {
  this.autorun(function (computation) {
    const posts = Posts.find({})

    // aggregate authors and comments
    const authorIds = []
    let commentIds = []
    posts.forEach(function (post) {
      authorIds.push(post.authorId)
      commentIds = _.union(commentIds, post.commentIds)
    })
    const authors = Authors.find({ _id: { $in: authorIds } })
    const comments = Comments.find({ _id: { $in: commentIds } })

    // return multiple cursors
    return [posts, authors, comments]
  })
})

#2

I have been doing something similar, except that I return only one cursor and add the joins into the documents, something like this

Meteor.publish('all-posts-with-comments-and-authors', function (query) {
 const self = this;
 const handle = Posts.find(query).observerChanges({
  added: function(id, post) {
   post.author = Authors.findOne( post.authorId );
   post.comments = Comments.find( {_id: {$in: post.commentIds}} );
   self.added('all-posts-with-comments-and-authors', id, post);
  }
 });
 self.ready();
 self.onStop(function () {
  if(handler) handler.stop();
 });
}