Node.js + MongoDB запрос не работает должным образом с объектом "$ or" - PullRequest
5 голосов
/ 27 февраля 2012

Я пытаюсь создать маршрут для пользователей, чтобы иметь возможность проверять профили других пользователей. Тем не менее, я хочу, чтобы эти профили принимались через 2 разных URL /profile/nickname и /profile/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: []  
        });
    }
});
});

Проблема в том, что, похоже, он работает только с идентификатором, а не с псевдонимом, что означает, что если я получаю доступ к /profile/4f4ae474546708b219000005, все работает, но если я получаю доступ к /profile/mmellad, который является данным псевдонимом для этого пользователя, Я получаю страницу 404.

Есть еще одна вещь, которую я понял, которая отлично работает для псевдонимов, которая меняет запрос с

User.findOne( { $or : [{ "nickname": req.params.id },{ "_id": req.params.id }] }

до

User.findOne( { "nickname": req.params.id } }

в этом случае /profile/mmellado работает нормально, но использование идентификатора пользователя, очевидно, не работает.

Что было бы правильным способом сделать это? Я думаю, что могу использовать неправильный подход.

Еще одна вещь, которую стоит упомянуть: если я попробую следующий код в консоли mongo, он также будет работать нормально:

x = db.users.findOne({ $or: [ {nickname:"mmellado"}, {_id:ObjectId("4f4ae474546708b219000005")}  ]})

Я протестировал этот код, вставив правильный псевдоним и неправильный _id, а затем протестировал с неправильным псевдонимом и правильным _id. В обоих случаях x в итоге содержал объект для нужной мне записи.

Я думаю, что смогу исправить это с помощью дополнительного маршрута, но я новичок в Node.js и Express вместе, так что я не уверен, каким будет подход с проппером.

Спасибо!

Ответы [ 2 ]

4 голосов
/ 27 февраля 2012

Вы пробовали это в консоли: x = db.users.findOne({ $or: [ {nickname:"mmellado"}, {_id:ObjectId("mmellado")} ]}).Вы увидите ошибку, даже если псевдоним совпадает, потому что он сначала пытается преобразовать «mmellado» в ObjectId и терпит неудачу.Это может быть причиной того, что ваша страница перестала работать при использовании псевдонима.

Я не знаю внутренности mongodb-драйвера для node.js, но она, вероятно, пытается преобразовать аргумент внутренне в ObjectId, прежде чем запрашивать "_id"поле (и не в состоянии, если не верно).Я не проверял это, так что попробуйте.Также попробуйте проверить объект err при обратном вызове.Если это проблема, то один из способов решить эту проблему - проверить, является ли аргумент действительным 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 );
}
0 голосов
/ 28 февраля 2012

Значения _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) { ........

Привет, Финч !!!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...