我正在尝试为用户创建一条路径,以便能够检查其他用户的个人资料。但是,我希望通过2个不同的网址/profile/nickname
和/profile/id
来加入这些个人资料,以便可以使用用户的昵称或用户ID来接收个人资料。我尝试了以下代码:
app.get("/profile/:id", function(req, res) {
User.findOne( { $or : [{ "nickname": req.params.id },{ "_id": req.params.id }] }, function(err, user) {
if(user)
{
res.render('users/profile.jade', {
locals: {
currentUser: user,
title: user.nickname +"'s Profile",
jsf:[],
}
});
}
else
{
res.render('404.jade', {
status: 404,
title: 'Page Not Found',
jsf: []
});
}
});
});
问题是,它似乎只是使用id而不是昵称,这意味着如果我访问/profile/4f4ae474546708b219000005
事情有效,但是如果我访问/profile/mmellad
这是给定的昵称对于该用户,我获得了404页面。
我还想到了另一件可以解决昵称的问题,即改变查询
User.findOne( { $or : [{ "nickname": req.params.id },{ "_id": req.params.id }] }
到
User.findOne( { "nickname": req.params.id } }
在这种情况下/profile/mmellado
工作正常,但显然没有使用用户ID。
这样做的正确方法是什么?我想我可能采用了错误的方法。
另外需要提及的是,如果我在mongo控制台中尝试以下代码,它也能正常工作:
x = db.users.findOne({ $or: [ {nickname:"mmellado"}, {_id:ObjectId("4f4ae474546708b219000005")} ]})
我通过插入正确的昵称和错误的_id来测试该代码,然后使用错误的昵称和正确的_id进行测试。在这两种情况下,x最终都包含了我需要的记录对象。
我想我可以通过一条额外的路线修复它,但我是Node.js和Express的新手,所以我不确定这个方法是什么。
谢谢!
答案 0 :(得分:4)
您是否在控制台中尝试了此操作:x = db.users.findOne({ $or: [ {nickname:"mmellado"}, {_id:ObjectId("mmellado")} ]})
。即使昵称匹配,您也会看到错误,因为它首先尝试将“mmellado”转换为ObjectId并失败。这可能是您在使用昵称时页面失败的原因。
我不知道node.js mongodb-driver内部,但它可能会在查询“_id”字段之前尝试将参数内部转换为ObjectId(如果无效则会失败)。我没有检查过,所以试一试。还尝试检查回调上的错误对象。如果这是问题,解决这个问题的一种方法是在查询之前检查参数是否是有效的ObjectId,例如自己创建ObjectId并在失败时捕获异常。这样的事情(未经测试):
try {
var objectId = createObjectId(req.params.id); // Create this function yourself
User.findOne( { "_id": objectId }, callbackFunction );
} catch (err) {
// Fall back to using nickname
User.findOne( { "nickname": req.params.id }, callbackFunction );
}
答案 1 :(得分:0)
默认的_id值是12字节的二进制哈希值,因此在使用ObjectID.createFromHexString发送查询之前,首先需要将字符串转换为二进制:
var id = ObjectID.createFromHexString(idHex);
然后在查询中使用id。
您的代码应如下所示:
User.findOne( { $or : [{ "nickname": req.params.id },{ "_id": ObjectID.createFromHexString(req.params.id) }] }, function(err, user) { ........
问候芬奇!!!