5

類似したアイテムをグループ化するアクティビティ ストリーム アイテムのリストがあります。たとえば、「Joe があなたの幸せな投稿を気に入った」、「Sarah があなたの幸せな投稿を気に入った」、「Bob があなたの幸せな投稿を気に入った」、「Tom があなたの幸せな投稿を気に入った」という 4 つのエントリの代わりに、「Joe があなたの幸せな投稿を気に入った」というエントリが必要です。さん、Sarah さん、他 2 人があなたの幸せな投稿を高く評価しました」. アイテムが集約されると、集約された投稿はその部分の最新のタイム スタンプを使用します。

アクティビティ ストリームは無限ではなく、過去 1 週間のアイテムのみを含むため、名詞 (noun.activityType + noun.id) と動詞のプロパティで一致するすべてのアイテムをグループ化する必要があります。各アクティビティ項目には、アクター (実行者)、ターゲット (投稿先のフィード)、動詞 (アクターが実行したこと)、および名詞 (動詞が実行されたオブジェクト) があります。

このテスト データセットを jsfiddle に置いて、みんなで遊んでもらいました。

http://jsfiddle.net/yu2P8/1/

{
        "pts": 0,
        "verb": "follow",
        "target": "mike",
        "actor": "test01",
        "title": "test01 has started following you",
        "published": "2012-06-04T22:34:01.914Z",
        "_id": "4fcd37d9c7f1f40100000d7d",
        "noun": {
            "id": "mike",
            "activityType": "profile",
            "title": null
        }
}

1 つの戦略は、アクティビティ アイテムの作成時にサーバー サイドを集約することですが、アンダースコアなどのライブラリを使用してクライアント サイドでこれを実行できるかどうかを調査したかったのです。

4

1 に答える 1

3

アンダースコアグループとマップを使用してこれを解決しました。最初に、名詞と動詞をキーとしてアンダースコア グループを使用します。次に、underscore reduce 関数を使用して、結果を 1 つのエントリに結合します。

var groupedResults = _.groupBy(data, function(val){
  return val.noun.id + val.noun.activityType + val.verb;
});

function reducer(activities, key) {
  var reduction = _.reduce(activities, function(a, b){
      if (a && a.actors && !_.include(a.actors, b.actor))
          a.actors.push(b.actor);
      else
          a.actors = [b.actor];
      a.published = a.published < b.published ? b.published : a.published;
      return a;

    }, activities[0]);

  reduction.pronoun = getActorsSummaryString(reduction);
  reduction.title = summarizeTitle(reduction);

  return reduction;
}

finalResults = sortByRecent(_.map(groupedResults, reducer));
于 2012-06-17T18:48:20.547 に答える