2016-07-12 6 views
1

У меня есть две коллекции: данные и пользователи. В коллекции данных имеется массив идентификаторов пользователей, состоящий из примерно 300 - 800 пользователей.Метеор: ускорение MongoDB Присоединиться к большим данным?

Мне нужно объединить страны всех пользователей для каждой строки в коллекции данных, которая зависает моего веб-браузера из-за слишком большого количества данных, которые запрашиваются сразу.

Я запрашиваю около 16 строк коллекции данных одновременно, а также есть 18833 пользователей в коллекции Пользователи.

До сих пор я пытался сделать как метод Метеор, так и преобразование() ПРИСОЕДИНЯЮТСЯ к коллекции 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; 
    } 
}); 

Сбор данных:

GlyphAllInOne Collection userInfo Collection

Существует опция PREPRO так что страны уже будут включены, однако мне не разрешено изменять эти коллекции. Я предполагаю, что если этот JOIN будет выполнен при запуске сервера и после этого выставлен через массив, поскольку метод Meteor может слишком долго останавливать время запуска сервера; хотя я не уверен.

Есть ли у кого-нибудь идеи о том, как ускорить этот запрос?

РЕДАКТИРОВАТЬ: Пробовал команды агрегации MongoDB, а также, как представляется, очень медленно на minimongo Meteor. Прошло 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}} 
    ]) 
+0

сбрасывать документы в тексте ..... – profesor79

+0

Мне не разрешено работать с документами в тексте проекта, над которым я работаю. – Dranithix

+0

Агрегация не работает против minimongo, она работает только на стороне сервера. –

ответ

0

решаемая проблема, создав огромный вызов агрегации MongoDB, с самым большим фактором в решении латентности является индексирование уникальных столбцов в базе данных.

После тщательного внедрения индексов в мою базу данных с более чем 4,6 миллионами записей на Robomongo потребовалось 0,3 секунды и 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; 
    } 
}); 

Если кто-то решает подобные вопросы, не стесняйтесь связаться со мной. Спасибо всем за вашу поддержку!

0

Я хотел бы подойти к этой проблеме несколько иначе, используя reywood:publish-composite

  1. На сервере я хотел бы опубликовать glyphinfo используя публиковать композит, а затем включить соответствующий пользователь и их поле страны в публикации
  2. Я бы присоединился к стране на клиенте везде, где мне нужно было указать название страны вместе с объектом 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 }}); 
      } 
     ] 
    } 
}); 
+0

Мне удалось создать публикацию успешно для # 1, однако # 2 потребовалось слишком много обработки, чтобы одновременно вызвать слишком много UserInfo.findOne(), чтобы она повесила мой браузер. Я пытаюсь получить распределение PeopleInfo в стране, чтобы я знал, сколько графов существует для каждой страны как массив, основанный на peopleInfo. – Dranithix

+1

# 2, вероятно, лучше всего оставить на монго-агрегации на сервере. –

Смежные вопросы