1

私は Win7(32) で meteor 0.3.7 を使用しており、2 つの MongoDB コレクションを使用して単純なログ システムを作成し、DBRef によってリンクされたデータを保存しようとしています。

現在の疑似スキーマは次のとおりです。

    Users {
      username : String,
      password : String,
      created  : Timestamp,
    }

    Logs {
      user_id : DBRef {$id, $ref}
      message : String
    }

サーバー メソッドを使用してログを挿入し、クライアント コレクションに対してアップサートを実行できるようにします。

ここで、古い「左結合」を実行し、ユーザー名が埋め込まれた最後の n 個のログのリストを表示したいと考えています。最も使用される操作は最後の n 個のログを取得するため、ユーザーにログを埋め込みたくありません。私の意見では、埋め込みはパフォーマンスに大きな影響を与えるでしょう。

これを達成するための最良のアプローチは何ですか?

次に、可能であればユーザー名を編集すると、すべての項目が名前を変更できてよかったです

よろしく

4

2 に答える 2

2

Cursor.observe をいじってみると、私の質問に答えてくれました。これは、これを行う最も効果的な方法ではないかもしれませんが、DBRef の「リンク」を逆参照するという私の将来の問題を解決します。

そのため、サーバーには特別なコレクションを公開する必要があります。カーソルを列挙し、対応する DBRef のドキュメント検索ごとに 1 つ。この実装はハードコードされており、UnRefCollection のようなパッケージとして実行する必要があることに注意してください。

サーバ側

    CC.Logs = new Meteor.Collection("logs");
    CC.Users = new Meteor.Collection("users");

Meteor.publish('logsAndUsers', function (page, size) {
    var self = this;
    var startup = true;  
    var startupList = [], uniqArr = [];

    page = page || 1;
    size = size || 100;
    var skip = (page - 1) * size;

    var cursor = CC.Logs.find({}, {limit : size, skip : skip});
    var handle = cursor.observe({
        added : function(doc, idx){
            var clone = _.clone(doc);
            var refId = clone.user_id.oid; // showld search DBRefs
            if (startup){
                startupList.push(clone);    
                if (!_.contains(uniqArr, refId))
                    uniqArr.push(refId);
            } else {
                // Clients added logs
                var deref = CC.Users.findOne({_id : refid});
                clone.user = deref;
                self.set('logsAndUsers', clone._id, clone);
                self.flush();
            }
        },
        removed : function(doc, idx){
            self.unset('logsAndUsers', doc._id, _.keys(doc));
            self.flush();
        },
        changed : function(new_document, idx, old_document){
            var set = {};
            _.each(new_document, function (v, k) {
              if (!_.isEqual(v, old_document[k]))
                set[k] = v;
            });
            self.set('logsAndUsers', new_document._id, set);
            var dead_keys = _.difference(_.keys(old_document), _.keys(new_document));
            self.unset('logsAndUsers', new_document._id, dead_keys);
            self.flush();
        },
        moved : function(document, old_index, new_index){
            // Not used
        }
    });

    self.onStop(function(){
        handle.stop();
    });

    //  Deref on first Run
    var derefs = CC.Users.find({_id : {$in : uniqArr} }).fetch();
    _.forEach(startupList, function (item){
        _.forEach(derefs, function(ditems){
            if (item["user_id"].oid === ditems._id){
                item.user = ditems;
                return false;
            }
        });
        self.set('logsAndUsers', item._id, item);
    });
    delete derefs; // Not needed anymore

    startup = false;
    self.complete();
    self.flush();
});

追加されたログ ドキュメントごとに、ユーザー コレクションを検索し、不足している情報をログ コレクションに追加しようとします。追加された関数は、最初の実行でログ コレクション内の各ドキュメントに対して呼び出されます。startupList と一意のユーザー ID の配列を作成したので、最初の実行ではデータベースに 1 回だけクエリを実行します。物事をスピードアップするためにページングメカニズムを配置することをお勧めします。

クライアント側

クライアントで、logsAndUsers コレクションをサブスクライブします。変更を加える場合は、Logs コレクションに対して直接行います。

LogsAndUsers = new Meteor.collection('logsAndUser');
Logs = new Meteor.colection('logs'); // Changes here are observed in the LogsAndUsers collection

Meteor.autosubscribe(function () {
    var page = Session.get('page') || 1;
    Meteor.subscribe('logsAndUsers', page);
});
于 2012-07-05T11:31:24.310 に答える
0

ログコレクションにもユーザー名を保存しないのはなぜですか? 次に、何らかの「結合」を必要とせずに、それらを直接クエリできます

なんらかの理由でそのユーザー名の変更を処理できるようにする必要がある場合は、ユーザー オブジェクトを名前で取得し、次のコマンドでログをクエリします。{ user_id : user._id }

于 2012-06-29T22:38:21.353 に答える