我使用此代码从mongo db(带有mongoose的nodejs)中的用户查询令牌:
UserMdl.find().exists('token').select('token').exec(function onUsersFound(err, userMdls) {
console.log(userMdls);
});
所以我得到了:
[ {
_id: 5447e36a60e5d15678de486c,
token: '34f83483cc0ed82e17c162d'
}, ... ]
有没有办法获得字符串数组:
[ '34f83483cc0ed82e17c162d', ... ]
现在我正在做的是对响应进行后期处理。我问这个问题是因为我认为在mongoose / mongodb查询中可能有更快的方法。
修改
后处理我现在正在做:
var results = [];
userMdls.forEach(function (userMdl) {
results.push(userMdl.token);
});
修改
感谢saintedlama的回应,我做了一些测试,结果就是这样:
数据:14.976份文件
测试:100
结果:
.find().exists('token').exec(..)
:1236.33 ms
.aggregate({..})
:136.07 ms
测试代码:
var start,
end,
time,
firstTimes = [],
secondTimes = [],
test = 0,
firstFinal,
secondFinal,
i,
Q = require('q'),
UserMdl = require('models/user'),
u,
tokens = [];
function promiseWhile(condition, body) {
var done = Q.defer();
function repeatTest() {
start = new Date().getTime();
UserMdl.find().exists('token').exec(function onUserMdlFound(err, users) {
for (u = 0; u < users.length; u += 1) {
tokens.push(users[u].token);
}
end = new Date().getTime();
time = end - start;
firstTimes.push(time);
start = new Date().getTime();
tokens = [];
UserMdl.aggregate({
$match: {
token: {
$exists: true
}
}
}, {
$project: {
_id: 0,
token: 1
}
}, function onUserMdlFoundAggregate(err, users) {
for (u = 0; u < users.length; u += 1) {
tokens.push(users[u].token);
}
end = new Date().getTime();
time = end - start;
secondTimes.push(time);
tokens = [];
if (condition()) {
Q.when(body(), repeatTest, done.reject);
} else {
return done.resolve();
}
});
});
}
Q.nextTick(repeatTest);
return done.promise;
}
function printResult() {
firstFinal = 0;
secondFinal = 0;
for (i = 0; i < firstTimes.length; i += 1) {
firstFinal += firstTimes[i];
secondFinal += secondTimes[i];
}
console.log("First mean: " + firstFinal / i + " - Second mean: " + secondFinal / i);
}
test = 1;
promiseWhile(function condition() {
return test <= 300;
}, function body() {
console.log("running test: " + test);
test++;
return Q.delay(0); // arbitrary async
}).then(function () {
console.log("Finish testing");
printResult();
}).done();
答案 0 :(得分:2)
有一种方法可以选择仅使用mongodb aggregation framework需要较少处理的令牌
UserMdl.aggregate(
{ $match: { token : { $exists : true }}},
{ $project: { _id: 0, token: 1 }},
function onUsersFound(err, tokens) {
console.log(tokens);
});
);
这构造了一个聚合管道,该管道首先匹配具有令牌字段的所有文档,然后选择令牌字段并使用_id : 0
管道步骤中的$project
来抑制_id选择。
后处理步骤如下所示:
function postProcess(tokenObjects) {
if (!tokenObjects) {
return [];
}
return tokenObjects.map(function(tokenObject) { return tokenObject.token; });
}
有关聚合函数的详细信息,另请参阅the mongoose docs。
答案 1 :(得分:1)
您不需要执行任何特殊操作。只需更改代码中的一件事即可:
您的代码
UserMdl.find().exists('token').select('token').exec(function onUsersFound(err, userMdls) {
console.log(userMdls); // (*) Change this to...
});
更改
UserMdl.find().exec((err, users) => {
console.log(users.map(user => user.token)); // ...(*) to this
});
无需使用select
和exists
函数
编辑
最好的选择是猫鼬distinct函数:
const tokens = await UserMdl.distinct('token');
如果您需要条件,那么:
const tokens = await UserMdl.find(/* condition */).distinct('token');
就这样