在 mongodb 中加入 1:many:many

Doing a 1:many:many join in mongodb

在这个 上,我的一些代码非常适合所讨论的场景。

我想为另一个类似的场景调整相同的代码,但我还没有弄明白哪里出了问题。这次我有一个 coursemodule 集合,一个 many:many 课程和模块之间的关系集合,它只存储 coursesIdmoduleId。由于代码运行完美,我简单地复制,做了一些修改,得到了下面的代码:

courses(){
    var theslug = FlowRouter.getParam('myslug');
    var mySchoolDocs = SchoolDb.findOne({slug: theslug});
    var arrayModuleSchools = ModuleSchool.find({schoolId: mySchoolDocs._id});
    // Transform the array of document into an array with only the ids
    var arrayModuleId = [];
    arrayModuleSchools.forEach(function(moduleSchools){
        arrayModuleId.push(moduleSchools.moduleId);
    });
    var coursetoMod = CourseModules.find({}, {moduleId: {$in: arrayModuleId}});
    if (coursetoMod) {
        coursesArrayIds = [];
        console.log(coursetoSchool);
        coursetoMod.forEach(function (courseToModules) {
            coursesArrayIds.push(courseToModules.coursesId);
        });
        return Courses.find({_id: {$in: coursesArrayIds}}).fetch();
    }
}

具体来说,Modules 集合中仅存在 2 个模块,其 ID 为 - xfLM9DEzhCMYQpQ32 and PTbZQ9cTG9pByFsY2。 CourseModule 集合有这个有文档:

{
    "_id" : "iXX4unJZRNcCw9bAm",
    "moduleId" : "PTbZQ9cTG9pByFsY2",
    "coursesId" : "FbgcdZxADHKRBj98z",
    "createdAt" : ISODate("2017-08-25T16:36:17.173Z"),
    "userId" : "n5rqFSHbhm7zqADyB"
}
{
    "_id" : "RAJJFjqAjGoDeNhko",
    "moduleId" : "PTbZQ9cTG9pByFsY2",
    "coursesId" : "ESAf6NGpZzXeioecp",
    "createdAt" : ISODate("2017-08-25T16:36:17.182Z"),
    "userId" : "n5rqFSHbhm7zqADyB"
}
{
    "_id" : "8ceuFwZK8Qduo5J5P",
    "moduleId" : "xfLM9DEzhCMYQpQ32",
    "coursesId" : "KnNj4GLcyMtvF8JmB",
    "createdAt" : ISODate("2017-08-25T16:38:15.368Z"),
    "userId" : "n5rqFSHbhm7zqADyB"
}

在我登录控制台时,我发现 selectorId 未定义:

L…n.Cursor {collection: LocalCollection, sorter: null, matcher: M…o.Matcher, _selectorId: undefined, skip: undefined…}_projectionFn: (obj)_selectorId: undefined_transform: nullcollection: LocalCollectionfields: undefinedlimit: undefinedmatcher: Minimongo.Matcherreactive: trueskip: undefinedsorter: null__proto__: Object_depend: (changers, _allow_unordered)_getCollectionName: ()_getRawObjects: (options)_publishCursor: (sub)constructor: (collection, selector, options)count: ()fetch: ()forEach: (callback, thisArg)getTransform: ()map: (callback, thisArg)observe: (options)observeChanges: (options)rewind: ()proto: Object view.js:30 L…n.Cursor {collection: LocalCollection, sorter: null, matcher: M…o.Matcher, _selectorId: undefined, skip: undefined…}

我只想获取当前通过模块显示的特定学校的附属课程。

您使用 find 函数的方式有误:

 var coursetoMod = CourseModules.find({}, {moduleId: {$in: arrayModuleId}});

find() 函数有两个参数:myCollection.find(query, projection)。当您按字段过滤文档时,它必须在 query 参数内。而 projection 参数用于选择要 return.

的字段

在您的情况下,您使用的参数如下:query: {}projection: {moduleId: {$in: arrayModuleId}}。但必须是:query: {moduleId: {$in: arrayModuleId}}

所以你只需要使用 $in 作为第一个参数:

 var coursetoMod = CourseModules.find({moduleId: {$in: arrayModuleId}});

顺便说一下,如果你想直接看到 return 由 console.log 中的 find 函数编辑的文档,请使用 .fetch() :

 var coursetoMod = CourseModules.find({moduleId: {$in: arrayModuleId}}).fetch();

MongoDB 查找函数文档:https://docs.mongodb.com/manual/reference/method/db.collection.find/

@gaetan 的答案是正确的,您需要使用查询参数而不是投影参数。使用与 Meteor 一起打包的 underscore 库,还可以在您的代码中进行一些其他的简化。

courses() {
  const slug = FlowRouter.getParam('myslug');
  const schoolId = SchoolDb.findOne({ slug })._id;
  const Modules = ModuleSchool.find({ schoolId });
  const ModuleIds = _.pluck(Modules,'moduleId');
  const coursetoMod = CourseModules.find({ moduleId: { $in: ModuleIds }});

  if (coursetoMod.length) {
    coursesIds = _.pluck(coursetoMod,'coursesId');
    return Courses.find({ _id: { $in: coursesArrayIds }}).fetch();
  }
}