Create join of two collections in MongoDB using Meteor JS

我是研究僧i 提交于 2020-01-06 03:24:07

问题


I have following data structure:

Collection books:

{
  _id: "ajafsoaifj3341",
  title: "Hello World",
  poems: [
      {
        id: "12fjenofnoi23",
        addedAt: "2018-03-12...."
      },
      {
        id: "563jdfb34jfrr",
        addedAt: "2018-03-10...."
      },
      {
        id: "78a1ewqeqweq",
        addedAt: "2018-03-08...."
      }
   ]
}

Collection poems:

{
  _id: "563jdfb34jfrr",
  title: "How to Join",
  author: "Smith"
  addedAt: "2017-12-21..."
}

I need to join these two collections to get the title of the poem. Something like:

{
  _id: "ajafsoaifj3341",
  title: "Hello World",
  poems: {
    id: "12fjenofnoi23",
    addedAt: "2018-03-12....",
    title: "How to Join"
  }
}

I fond an example like this:

//SERVER
import { Poems } from '../imports/collections/poems';
import { Books } from '../imports/collections/books';

Meteor.publish('booksWithPoems', function (bookId) {
  const book = Books.findOne({ _id: bookId });
  return [
    Books.find({ _id: bookId }),
    Poems.find({
      _id: {
        $in: book.poems.id
      }
    })
  ];
});

//CLIENT
export default withTracker(props => {
const bookSubscription = Meteor.subscribe('booksWithPoems', props.editBookId);
return {
    editedBook: Books.findOne({}),
    editedPoems: Poems.find({}).fetch(),
    bookLoaded: bookSubscription.ready()
};
})(connect(mapStateToProps, {    
    ...
})(withRouter(BookEditor)));

But this.props.editedPoems is undefined. What is wrong here?

Maybe this are better ways to do this. I would appreciate if you could help me both with server and client code. I am quite new in Meteor/Mongo world.

And the last comment. I do not need all data from Poem documents, just "title". Thanks!


回答1:


Your publication has the following problematic part: $in excpects an array, while book.poems.id is a String value on a single poem. What you want, however is an array of all ids in book.poems.

This is also the cause while the other subscription (editedBook) receives some data and editedPoems not. Subscription reflect only those documents, that have been found in the last execution of the publication method.

In order to get this correct you need to first map Poems ids and set this array as value for $in:

Meteor.publish('booksWithPoems', function (bookId) {
  const book = Books.findOne({ _id: bookId });
  return [
    Books.find({ _id: bookId }),
    Poems.find({
      _id: {
        $in: book.poems.map( p => p.id ), // ["12fjenofnoi23","563jdfb34jfrr","78a1ewqeqweq"]
      }
    })
  ];
});

Now it should select all poems, whose id fits one of the ids provided in the array, assigned to $in.

I have not checked the client code and the way you join the data, but I think this mongo query selector is the main issue here.

More to read on $in: https://docs.mongodb.com/manual/reference/operator/query/in/



来源:https://stackoverflow.com/questions/49306048/create-join-of-two-collections-in-mongodb-using-meteor-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!