1

Data と Users の 2 つのコレクションがあります。データ コレクションには、約 300 ~ 800 人のユーザーで構成されるユーザー ID の配列があります。

データ コレクションの各行のすべてのユーザーの国を結合する必要があります。一度にクエリされるデータが多すぎるため、Web ブラウザーがハングします。

一度に Data コレクションの約 16 行をクエリし、これまでに Users コレクションに 18833 人のユーザーがいます。

これまでのところ、Meteor メソッドと、アプリをハングさせている Meteor コレクションの transform() JOIN の両方を作成しようとしました。

モンゴ コレクション:

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 コレクション userInfo コレクション

国が含まれるようにコレクションを前処理するオプションがありますが、これらのコレクションを変更することはできません。この JOIN をサーバーの起動時に実行し、その後 Meteor メソッドとして配列を介して公開すると、サーバーの起動時間が長すぎる可能性があると思います。よくわかりませんが。

このクエリを高速化する方法について誰かアイデアがありますか?

編集: MongoDB 集計コマンドも試してみましたが、Meteor の minimongo では非常に遅いようです。ネイティブ MongoDB クライアントでは 1 秒かかるのに対し、クエリには 4 分かかりました。

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}}
    ])
4

2 に答える 2

0

reywood:publish-compositeを使用して、この問題に少し違ったアプローチをします。

  1. サーバー上で、publish-composite を使用して 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 }});
            }
        ]
    }
});
于 2016-07-12T17:56:48.410 に答える
0

巨大な MongoDB 集計呼び出しを作成することで問題を解決しました。遅延を解決する最大の要因は、データベース内の一意の列にインデックスを作成することです。

460 万を超えるエントリを持つデータベースにインデックスを慎重に実装した後、Robomongo で 0.3 秒、Meteor でクライアントにデータを送信するのに 1.4 秒かかりました。

見たい人のための集計コードは次のとおりです。

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;
    }
});

他の誰かが同様の問題に取り組んでいる場合は、遠慮なく私に連絡してください。ご支援いただきありがとうございます!

于 2016-07-13T07:01:09.427 に答える