2012-02-27 10 views
5

Próbuję utworzyć trasę dla użytkowników, aby móc sprawdzać profile innych użytkowników. Jednak chcę, aby te profile były dostępne za pośrednictwem dwóch różnych adresów URL: /profile/nickname i /profile/id, aby umożliwić odczyt profilu za pomocą pseudonimu użytkownika lub identyfikatora użytkownika. Próbowałem następujący kod:

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: [] 
     }); 
    } 
}); 
}); 

Problem polega na tym, wydaje się, że działa tylko z identyfikatorem, a nie z pseudonimu, co oznacza, że ​​jeśli acces /profile/4f4ae474546708b219000005 wszystko działa, ale jeśli mam dostępu /profile/mmellad który jest podałem pseudonim dla tego użytkownika, otrzymuję stronę 404.

Jest jeszcze jedna rzecz, zorientowali się, że działa dobrze dla pseudonimów, który zmienia zapytanie z

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

do

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

w tym przypadku /profile/mmellado działa dobrze, ale przy użyciu identyfikator użytkownika oczywiście nie.

Jaki byłby właściwy sposób, aby to zrobić? Myślę, że mogę używać niewłaściwego podejścia.

Inną rzeczą, aby wspomnieć, że gdy próbuję następujący kod w konsoli Mongo, współpracuje także:

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

Testowałem tego kodu poprzez wstawienie odpowiedniego pseudonimu i złego _id, a następnie przetestowany ze złym pseudonimem i prawym _id. W obu przypadkach x zakończył się tym, że zawierał obiekt dla potrzebnego rekordu.

Myślę, że mogę go naprawić dodatkową trasą, ale jestem nowy dla Node.js i Express wszystkie razem, więc nie jestem pewien, co byłoby podejście proppera.

Dzięki!

+0

Którą wersję Mongo używasz? –

+0

wersja Mongo jest następujący: Marcos-Mellados-iMac-2: ~ Marcos $ mongod --version db v2.0.2, wersja pdfile 4,5 Pon 27 lutego wersji 02:48:11 git: 514b122d308928517f5841888ceaa4246a7f18e3 –

Odpowiedz

4

Wypróbowałeś to w konsoli: x = db.users.findOne({ $or: [ {nickname:"mmellado"}, {_id:ObjectId("mmellado")} ]}). Pojawi się błąd, nawet jeśli pseudonim się zgadza, ponieważ najpierw próbuje przekonwertować "mmellado" na identyfikator obiektu i nie powiedzie się. Może to być przyczyną niepowodzenia Twojej strony podczas używania pseudonimu.

Nie znam wewnętrznych obiektów node.js, ale prawdopodobnie spróbuję przekonwertować argument wewnętrznie na ObjectId przed zapytaniem o pole "_id" (i jeśli nie, to się nie powiedzie). Nie sprawdziłem tego, więc wypróbuj to. Spróbuj także sprawdzić obiekt err w wywołaniu zwrotnym. Jeśli jest to problem, jednym ze sposobów rozwiązania tego problemu jest sprawdzenie, czy argument jest prawidłowym ObjectId przed wysłaniem zapytania, na przykład samodzielne utworzenie obiektu ObjectId i wychwycenie wyjątku, jeśli się nie powiedzie. Coś jak to (nie testowane):

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

próbowałem drukowanie kodu błędu w czasie zapytania. Oto, co otrzymuję: [Błąd: Niepoprawny ObjectId], Moje założenie jest takie, że gdy próbuję użyć Fincha jako parametru, a warunek przechodzi przez część _id, ponieważ podany ciąg nie jest poprawnym ObjectId, zapytanie pęka, zwracając błąd ... nie dając wyniku, nawet jeśli część zapytania działała ... jakieś pomysły na obejście tego problemu? –

+0

@MarcosMellado To wydaje się wspierać moje myśli. Zaproponowałem rozwiązanie w moim poście, zmodyfikowałem je, aby dodać przykładowy kod, aby było bardziej zrozumiałe. – Lycha

+0

Właściwie to doszedłem do BARDZO podobnego rozwiązania, zrobię odpowiednie zmiany, aby działał z próbą catch i dadzą ci znać, czy zadziałało :) –

0

domyślne wartości _id są 12 bajtowe hashe binarne więc trzeba najpierw przekonwertować ciąg do pliku binarnego przed wysłaniem zapytania używając ObjectID.createFromHexString tak:

var id = ObjectID.createFromHexString(idHex); 

Następnie użyj id w zapytaniu.

Kod powinien wyglądać mniej więcej tak:

User.findOne({ $or : [{ "nickname": req.params.id },{ "_id": ObjectID.createFromHexString(req.params.id) }] }, function(err, user) { ........ 

Greetings Fincha !!!

+0

Jak zdefiniowałbyś ObjectId? W tej chwili mam mangustę = wymaganie ("mangusta"), \t \t ObjectID = mangusta.Schema.ObjectId, –

+0

Zignoruj ​​ostatni komentarz, problem z jego podejściem, w momencie wysyłania pseudonim jako parametr i przekazywanie go poprzez funkcję createFromHexString, generuje następny błąd: Błąd: Argument przekazany musi być pojedynczym ciągiem 12 bajtów lub ciągiem 24 znaków szesnastkowych w formacie szesnastkowym (zakładając, że pseudonim jest na przykład zgrubny) –

+0

Ture, spróbuj najpierw przekonwertować Twój ciąg (Finch) do ciągu szesnastkowego za pomocą: var hexString = nickname.toHexString(); - następnie przekazujemy to jako argument do utworzenia obiektu objectID – user313551