jak używać mapreduce w subdokumentie zapytania mongoose / mongodb?
Zaimplementowałem prosty system wiadomości w mongoose / mongodb, schemat jest podobny do następującego
var schema = new mongoose.Schema({
user: {type:String, required:true},
updated: {type:Date, default:new Date()},
msgs: [ {m:String, // message itself
d:Date, // date of message
s: String, // message sender
r:Boolean // read or not
} ],
});
wszystkie wiadomości są przechowywane w zagnieżdżonej tablicy msg, teraz chcę wysłać zapytanie do niektórych nadawców, na przykład,
{
"_id" : ObjectId("52c7cbe6d72ecb07f9bbc148"),
'user':'abc'
"msgs" : [{
"m" : "I want to meet you",
"d" : new Date("4/1/2014 08:52:54"),
"s" : "user1",
"r" : false,
"_id" : ObjectId("52c7cbe69d09f89025000005")
}, {
"m" : "I want to meet you",
"d" : new Date("4/1/2014 08:52:56"),
"s" : "user1",
"r" : false,
"_id" : ObjectId("52c7cbe89d09f89025000006")
}, {
"m" : "I want to meet you",
"d" : new Date("4/1/2014 08:52:58"),
"s" : "user2",
"r" : false,
"_id" : ObjectId("52c7cbea9d09f89025000007")
}
}
Tutaj mam dokument dla użytkownika „aa”, który ma trzy wiadomości, dwie wiadomości pochodzą z „user1”, a jedna wiadomość z „user2”. I chcę zapytać o wiadomości od użytkownika „user1”
Zasadniczo istnieją dwa sposoby, aby to zrobić, zminimalizować lub zagregować. Spróbowałem rozwiązania zmniejszającego mapę.
var o = {};
o.map = function() {
this.msgs.forEach(function(msg){
if(msg.s == person){ emit( msg.s, {m:msg.m,d:msg.d,r:msg.r}); }
})
}
o.reduce = function(key, values) {
var msgs = [];
for(var i=0;i<values.length;i++)
msgs.push(values[i]);
return JSON.stringify(msgs);
}
o.query = {user:'username'};
o.scope = {person:'user1'};
model.mapReduce(o,function (err, data, stats) {
console.log('map reduce took %d ms', stats.processtime)
if(err) callback(err);
else callback(null,data);
})
Ostatecznie działa z takimi wynikami jak
[
{ _id: 'helxsz',
value: '[
{"m":"I want to meet you","d":"2014-01-04T08:52:54.112Z","r":false}, ....
]
]
Rezultat jest tym, czego chcę, ale format jest trochę skomplikowany. Jak mogę zmienić, aby format wyjściowy był taki jak ten
{ sender: 'helxsz',
messages: '[
{"m":"I want to meet you","d":"2014-01-04T08:52:54.112Z","r":false}, ...
]
}
i w jaki sposób sortuję i ograniczam wyniki, więc muszę ręcznie zrobić funkcję redukcji?
a ostatnia metoda zmniejszania mapy zajmuje 28 ms na zapytanie wyniku, w symulacji moja kolekcja ma trzy dokumenty, każdy dokument ma tablicę msg złożoną z 4 poddokumentów. dla mnie 28 ms to trochę za dużo dla zapytania, prawda? Teraz indeksowałem także w polu „użytkownik”.