Sails.js:嵌套 MongoDB 查询
Sails.js: Nested MongoDB queries
我正在使用 Sails v0.11 并正在开发一个独立的导入程序脚本以便将数据导入 mongoDB 并且 - 现在是不工作的部分 - 建立模型之间的关联。
对于这个过程,我在模型中引入了临时辅助属性,以便找到关联的记录并用真实的 MongoDB _ids 替换它们。
脚本启动 Sails 以便能够使用其功能(水线等):
var app = Sails();
app.load({
hooks: { grunt: false },
log: { level: 'warn' }
}, function sailsReady(err){
processUsers() 查找所有用户及其 _id 并迭代它们以调用第二个函数 addOrgsToOneUser()
var processUsers = function() {
// Iterate through all users in order to retrieve their _ids and
app.models['user'].native(function(err, collection) {
collection.find({}, projectionOrgInUser).toArray(function (err, users) {
Async.eachSeries(users, function (user, next){
// prepare userInOrgs
whereUserInOrg = { orgId: { $in: userInOrgs } };
//This is invoking
addOrgsToOneUser(user, whereUserInOrg);
next();
}, function afterwards (err) {
if (err) {
console.error('Import failed, error details:\n',err);
return process.exit(1);
}
console.log("done");
return process.exit(0); // This returns too early, not executing the addOrgsToOneUser
});
});
});
};
addOrgsToOneUser() 查找属于该用户的所有组织,然后更新该用户
的组织数组 属性
var addOrgsToOneUser = function(user, whereUserInOrg) {
var projectionUserInOrg = "...";
// Find all orgs that this user is associated to and store it in inOrgs
app.models['org'].native(function(err, collection) {
collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) {
// prepare inOrgs which is needed for updating
//update user to have an updated orgs array based on inOrgs.
app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){
console.log('Updated user ' + user._id.toString() + ' to be in their orgs');
});
});
});
}
问题:
- Process.exit(0) 在 saddOrgsToOneUser() 的 query/update 完成之前调用。例如,如果 saddOrgsToOneUser() 仅包含 console.log,它的行为与预期一致,但查询当然是异步触发的。
- 如果我注释掉 Process.exit(0),脚本永远不会停止,但查询会按预期执行。
- 由于脚本将有更多的嵌套查询,我需要一个更好的方法来手动终止这个脚本...
- 如何正确地嵌套查询和迭代其结果?
非常感谢,
曼纽尔
addOrgsToOneUser 是异步的。在 addOrgsToOneUser 内部完成所有操作后,需要调用 next()。我会这样做的方式是传递一个回调(下一步)并在一切完成后调用它。所以调用是
addOrgsToOneUser(user, whereUserInOrg, next);
并且 addOrgsToOneUser 将有一个额外的参数:
var addOrgsToOneUser = function(user, whereUserInOrg, callback) {
var projectionUserInOrg = "...";
// Find all orgs that this user is associated to and store it in inOrgs
app.models['org'].native(function(err, collection) {
collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) {
// prepare inOrgs which is needed for updating
//update user to have an updated orgs array based on inOrgs.
app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){
console.log('Updated user ' + user._id.toString() + ' to be in their orgs');
callback(); // your original next() is called here
});
});
});
}
我正在使用 Sails v0.11 并正在开发一个独立的导入程序脚本以便将数据导入 mongoDB 并且 - 现在是不工作的部分 - 建立模型之间的关联。
对于这个过程,我在模型中引入了临时辅助属性,以便找到关联的记录并用真实的 MongoDB _ids 替换它们。
脚本启动 Sails 以便能够使用其功能(水线等):
var app = Sails(); app.load({ hooks: { grunt: false }, log: { level: 'warn' } }, function sailsReady(err){
processUsers() 查找所有用户及其 _id 并迭代它们以调用第二个函数 addOrgsToOneUser()
var processUsers = function() { // Iterate through all users in order to retrieve their _ids and app.models['user'].native(function(err, collection) { collection.find({}, projectionOrgInUser).toArray(function (err, users) { Async.eachSeries(users, function (user, next){ // prepare userInOrgs whereUserInOrg = { orgId: { $in: userInOrgs } }; //This is invoking addOrgsToOneUser(user, whereUserInOrg); next(); }, function afterwards (err) { if (err) { console.error('Import failed, error details:\n',err); return process.exit(1); } console.log("done"); return process.exit(0); // This returns too early, not executing the addOrgsToOneUser }); }); }); };
addOrgsToOneUser() 查找属于该用户的所有组织,然后更新该用户
的组织数组 属性var addOrgsToOneUser = function(user, whereUserInOrg) { var projectionUserInOrg = "..."; // Find all orgs that this user is associated to and store it in inOrgs app.models['org'].native(function(err, collection) { collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) { // prepare inOrgs which is needed for updating //update user to have an updated orgs array based on inOrgs. app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){ console.log('Updated user ' + user._id.toString() + ' to be in their orgs'); }); }); }); }
问题:
- Process.exit(0) 在 saddOrgsToOneUser() 的 query/update 完成之前调用。例如,如果 saddOrgsToOneUser() 仅包含 console.log,它的行为与预期一致,但查询当然是异步触发的。
- 如果我注释掉 Process.exit(0),脚本永远不会停止,但查询会按预期执行。
- 由于脚本将有更多的嵌套查询,我需要一个更好的方法来手动终止这个脚本...
- 如何正确地嵌套查询和迭代其结果?
非常感谢, 曼纽尔
addOrgsToOneUser 是异步的。在 addOrgsToOneUser 内部完成所有操作后,需要调用 next()。我会这样做的方式是传递一个回调(下一步)并在一切完成后调用它。所以调用是
addOrgsToOneUser(user, whereUserInOrg, next);
并且 addOrgsToOneUser 将有一个额外的参数:
var addOrgsToOneUser = function(user, whereUserInOrg, callback) {
var projectionUserInOrg = "...";
// Find all orgs that this user is associated to and store it in inOrgs
app.models['org'].native(function(err, collection) {
collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) {
// prepare inOrgs which is needed for updating
//update user to have an updated orgs array based on inOrgs.
app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){
console.log('Updated user ' + user._id.toString() + ' to be in their orgs');
callback(); // your original next() is called here
});
});
});
}