Метеор: Ускорение MongoDB Регистрация для больших данных?
У меня есть две коллекции: данные и пользователи. В разделе "Сбор данных" имеется массив идентификаторов пользователей, состоящий примерно из 300–800 пользователей.
Мне нужно объединить страны всех пользователей для каждой строки в Сборе данных, что приводит к зависанию моего веб-браузера из-за слишком большого количества данных, запрашиваемых одновременно.
Я запрашиваю около 16 строк в Собрании данных одновременно, и на данный момент в коллекции "Пользователи" 18833 пользователя.
До сих пор я пытался создать как метод Meteor, так и метод transform() JOIN для коллекции Meteor, которая вешает мое приложение.
Монго Коллекция:
UserInfo = new Mongo.Collection("userInfo")
GlyphInfo = new Mongo.Collection("GlyphAllinOne", {
transform: function(doc) {
doc.peopleInfo = doc.peopleInfo.forEach(function(person) {
person.code3 = UserInfo.findOne({userId: person.name}).code3;
return person;
})
return doc;
}
});
"code3" обозначает страну пользователя.
Публикация:
Meteor.publish("glyphInfo", function (courseId) {
this.unblock();
var query = {};
if (courseId) query.courseId = courseId;
return [GlyphInfo.find(query), UserInfo.find({})];
})
Метод проверенного сервера:
Meteor.methods({
'glyph.countryDistribution': function(courseId) {
var query = {};
if (courseId) query.courseId = courseId;
var glyphs = _.map(_.pluck(GlyphInfo.find(query).fetch(), 'peopleInfo'), function(glyph) {
_.map(glyph, function(user) {
var data = Users.findOne({userId: user.name});
if (data) {
user.country = data ? data.code3 : null;
console.log(user.country)
return user;
}
});
return glyph;
});
return glyphs;
}
});
Сбор данных:
Существует возможность предварительной обработки моей коллекции, чтобы страны уже были включены, однако мне не разрешено изменять эти коллекции. Я предполагаю, что выполнение этого JOIN будет выполнено при запуске сервера и после этого будет показано через массив в качестве метода Meteor, что может слишком долго задерживать время запуска сервера; хотя я не уверен.
У кого-нибудь есть идеи как ускорить этот запрос?
РЕДАКТИРОВАТЬ: Испытаны агрегирующие команды MongoDB, и, кажется, это очень медленно на минимонго Метеора. Потребовалось 4 минуты для запроса по сравнению с 1 секундой на собственном клиенте MongoDB.
var codes = GlyphInfo.aggregate([
{$unwind: "$peopleInfo"},
{$lookup: {
from: "users",
localField: "peopleInfo.name",
foreignField: "userId",
as: "details"
}
},
{$unwind: "$details"},
{$project: {"peopleInfo.Count": 1, "details.code3": 1}}
])
2 ответа
Решил проблему, создав огромный вызов агрегации MongoDB, при этом основным фактором, определяющим задержку, является индексирование уникальных столбцов в вашей базе данных.
После тщательного внедрения индексов в мою базу данных с более чем 4,6 миллионами записей потребовалось 0,3 секунды для Robomongo и 1,4 секунды с отправкой данных клиенту на Meteor.
Вот код агрегации для тех, кто хотел бы его увидеть:
Meteor.methods({
'course.countryDistribution': function (courseId, videoId) {
var query = {};
if (courseId) query.courseId = courseId;
var data = GlyphInfo.aggregate([
{$unwind: "$peopleInfo"},
{$lookup: {
from: "users",
localField: "peopleInfo.name",
foreignField: "userId",
as: "details"
}
},
{$unwind: "$details"},
{$project: {"peopleInfo.Count": 1, "details.code3": 1}},
{$group: {_id: "$details.code3", count: {$sum: "$peopleInfo.Count"}}}
])
return data;
}
});
Если кто-то еще занимается аналогичными проблемами, не стесняйтесь связаться со мной. Спасибо всем за вашу поддержку!
Я хотел бы подойти к этой проблеме немного по-другому, используя Рейвуд: Publish-Composite
- На сервере я бы опубликовал информацию о глифе с помощью publish-смесь, а затем включил в публикацию связанного пользователя и поле его страны.
- Я бы присоединился к стране на клиенте везде, где мне нужно было отобразить название страны вместе с объектом glyphinfo
Публикация:
Meteor.publishComposite('glyphInfo', function(courseId) {
this.unblock();
return {
find: function() {
var query = {};
if (courseId) query.courseId = courseId;
return GlyphInfo.find(query);
},
children: [
{
find: function(glyph) {
var nameArray = [];
glyph.person.forEach(function(person){
nameArray.push(person.name);
};
return UserInfo.find({ userId: {$in: nameArray }});
}
]
}
});