0

私は、10Gen Socialite Project と非常によく似たソーシャル アクティビティ フィード システムに取り組んでいます。このプロジェクトは、数年前から運用されています。ユーザーごとに年代順に並べられたアクティビティのリストを保存する必要がある新しいユースケースがあります。アクティビティのリストは次のようにする必要があります。

  1. 最近挿入された N 個のアイテムのみを含む
  2. 意味的に同等のアイテムの重複を挿入しない
  3. 結果のページングを許可します。

これまでのところ、これを解決するための 2 つのアプローチを考え出しましたが、どちらにも厄介な制限があるようです。

最初のアプローチ (私の他のコレクションとよく似ています) は、アクティビティごとに 1 つのドキュメントを含む単一のコレクションを作成し、ユーザー ID でインデックスを作成することです。例えば:

{
    "owner": {
      "type": "user",
      "id" : "1234"
    },
    "activity": {
        "published": "2013-09-27T17:08:26+00:00",
        "actor": {
            "type": "elastic-search-node",
            "id": "2"
        },
        "verb": "recommend",
        "object": {
            "type": "review",
            "id": "1093773"
        }
        "uuid": "6d70eaa4-0766-4949-971d-98740cb9eca1"
    }
}

特定のユーザーの新しいアクティビティを受け取るたびに、同じ「所有者」句で異なる「アクティビティ」句を使用して、上記のドキュメントを挿入します。ただし、挿入を処理する最も効率的な方法はわかりません。上記の基準を考えると、1 つの疑似コード アプローチは次のようになります。

results = collection.update(
  {
    'owner.id':'1234', 
    'activity.verb':'recommend',
    'activity.object.type':'review',
    'activity.object.id':'1093773'
  },
  the_activity,
  upsert:true)

# count documents for owner.id = 1234
# if count > max_documents, delete oldest document

このアプローチの問題は、挿入とプルーニングを完了するのに最大 3 回のデータベース操作が必要になることです。ただし、「upsert」を使用すると重複が防止され、生成された ObjectID を一時的なクエリとページネーションに使用できます。

私が調べた別のアプローチは、Socialite のFanoutOnWriteSizedBucketsアプローチに似ています。この場合、アクティビティのリストは最大サイズの配列にサブドキュメントとして格納され、ユーザー ID によってインデックスが付けられます。例えば:

{
    "owner" : {"type":"user", "id":"1234"},
    "feed" : [
        {"_id" : ObjectId("...da7"), "activity" : ...},
        {"_id" : ObjectId("...dc1"), "activity" : ...},
        {"_id" : ObjectId("...dd2"), "activity" : ...}
    ]
}

この場合、クエリもかなり簡単ですが、ここでも挿入に問題があります。$update、$push、$addToSet、$ne、$each などのさまざまな手法と組み合わせを使用して調べましたが、重複挿入の防止とプルーニング操作をより効率的な方法で達成できるものはないようです。その上。

このユースケースを解決するためのアプローチを提案できる人はいますか?

ありがとう!

( mongodb -user Google グループに x 投稿) 解決済み : https://groups.google.com/forum/#!topic/mongodb-user/K8n7Gf1nv3Q

4

0 に答える 0