【问题标题】:Create join of two collections in MongoDB using Meteor JS使用 Meteor JS 在 MongoDB 中创建两个集合的连接
【发布时间】:2018-08-24 15:40:53
【问题描述】:

我有以下数据结构:

收藏书籍:

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

诗集:

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

我需要加入这两个集合才能得到这首诗的标题。比如:

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

我喜欢这样的例子:

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

但是 this.props.editedPoems 是未定义的。这里有什么问题?

也许这是更好的方法。如果您能帮助我处理服务器和客户端代码,我将不胜感激。我是 Meteor/Mongo 世界的新手。

最后一条评论。我不需要诗歌文档中的所有数据,只需要“标题”。谢谢!

【问题讨论】:

  • 您需要一些独特的东西才能加入。看看这个关于如何在 mongodb docs.mongodb.com/manual/reference/operator/aggregation/lookup 中加入
  • 能否添加PoemBook 的架构?我假设您想获取与一本书相关的所有诗歌,对吧?
  • 你是对的,Jankapunkt。我刚刚更新了诗歌集的结构。我希望现在更清楚了。 :)

标签: mongodb join meteor collections


【解决方案1】:

您的出版物有以下问题部分:$in 排除数组,而book.poems.id 是一首诗的字符串值。但是,您想要的是 book.poems 中所有 id 的数组。

这也是另一个订阅 (editedBook) 收到一些数据而 editedPoems 没有收到的原因。订阅仅反映在发布方法的最后执行中找到的那些文档。

为了得到这个正确你需要首先map Poems ids 并将这个数组设置为$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"]
      }
    })
  ];
});

现在它应该选择所有诗歌,其 id 符合数组中提供的 id 之一,分配给$in

我没有检查客户端代码和你加入数据的方式,但我认为这个 mongo 查询选择器是这里的主要问题。

更多关于 $in 的内容:https://docs.mongodb.com/manual/reference/operator/query/in/

【讨论】:

  • 谢谢你,扬卡朋克特!现在它正在工作。客户端代码没问题。我刚刚添加了 { fields: { title: 1 } }) 来获取标题。 ;-)
  • 你有关于性能的cmets吗?我觉得应该挺好的。有没有更好的方法来提供更好的性能?
  • 如果没有明确需要将文档存储在其他文档上,您可以通过仅将_id 值存储在book.poems 中来避免映射功能,您通常可以通过 Id 来引用。这首先在 DB 设计方面付出了更多努力,但增加了良好的可扩展性。
  • 我正在为书中的每首诗保存id。不一样吗?一首诗可以在不同的书中。
  • 现在我正在尝试在书中添加一首新诗,而收藏“书”又带着一首新诗回来了。没错。但是集合'诗'没有更新,并且不包含添加的诗的标题。仅仅是反应性的“书籍”吗?我预计“诗歌”会返回添加的标题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
相关资源
最近更新 更多