在 mongodb 中加入 1:many:many
Doing a 1:many:many join in mongodb
在这个 上,我的一些代码非常适合所讨论的场景。
我想为另一个类似的场景调整相同的代码,但我还没有弄明白哪里出了问题。这次我有一个 coursemodule
集合,一个 many:many 课程和模块之间的关系集合,它只存储 coursesId
和 moduleId
。由于代码运行完美,我简单地复制,做了一些修改,得到了下面的代码:
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();
}
}
在这个
我想为另一个类似的场景调整相同的代码,但我还没有弄明白哪里出了问题。这次我有一个 coursemodule
集合,一个 many:many 课程和模块之间的关系集合,它只存储 coursesId
和 moduleId
。由于代码运行完美,我简单地复制,做了一些修改,得到了下面的代码:
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();
}
}