0

私は次のスキーマを持っています:

  • クライアントID
  • 場所の名前
  • 訪問時間
  • 購入した // これはリストです

これは非構造化データであるため、MongoDB のようなフラット DB が自然に適合します。MongoDB を使用しています。

このデータには、クライアントの訪問情報がさまざまな場所に保存されます。特定の日の繰り返し訪問数を調べたいとします。繰り返し訪問のロジックは単純です。今日店舗を訪れた人が以前に同じ店舗を訪れていた場合、その人はその店舗のリピート訪問者です。

私は繰り返し訪問者の数を知ることができるロジックを持っています:

クエリ: Select * From Schema order by Location ID ASC , Client ID ASC, 'Time of Visit' ASC

上記のクエリのデータが並べ替えられると、LocationID と Client ID が一致する場合、「訪問時間」の前後の行を比較できます。差が 1 日以上ある場合は、再訪問です。

このデータは非常に大きいため、結合タイプのクエリは非常に非効率的です (MongoDB で可能であったとしても)。

これで、MongoDB に map reduce フレームワークがあることがわかりました。ただし、以前のレコードと現在のレコードを比較し、それに基づいて計算を行った後、map/reduce をトリガーすることは可能ですか?

例 :

  • 顧客 A が 1 日目に店舗 B を訪問 // 再訪問なし
  • 顧客 A が 1 日目に再び店舗 B を訪問 // まだ再訪問なし
  • 顧客 A が 2 日目に店舗 B を訪問 // この顧客 A は 2 日目に再訪問
  • 顧客 A が 2 日目に B 店に来店 // 2 日目にはすでに再来店としてカウントされています
  • 顧客 A が 3 日目に店舗 B を訪問 // この顧客は 3 日目に再訪問

  • 顧客 C は 2 日目に店舗 B を訪問します // 顧客 C の最初の訪問であり、再訪問ではありません

  • 顧客 C は 2 日目に再び店舗 B を訪問します // 訪問の初日であり、再訪問ではありません
  • 顧客 C が 3 日目に店舗 B を訪問 // 3 日目に再訪問
  • 顧客 C が 4 日目に店舗 B を訪問 // 4 日目に再訪問

  • 顧客 D が 5 日目に店舗 B を訪問 // 再訪問ではなく初回訪問

再訪問の最終結果:

  • 店舗 B、1 日目: 0 回の再来店
  • 店舗 B、2 日目: 2 回の再来店
  • 店舗 B、3 日目: 2 回の再来店
  • 店舗 B、4 日目: 1 回の再来店
  • 店舗 B、5 日目: 0 回の再来店
4

1 に答える 1

0

リレーショナル データベースでこれを行う場合、行ごとに訪問を比較するのではなく、集計クエリを使用して (SELECT ... GROUP BY を使用して) 繰り返しの訪問を見つけるので、MongoDB でも同じ方法で行う必要があります。

まず、1 日あたりの店舗ごとの顧客ごとの訪問数を集計する必要があります。

group1 = { "$group" : {
        "_id" : {
            "c" : "$clientId",
            "l" : "$location",
            "day" : {
                "y" : {
                    "$year" : "$tov"
                },
                "m" : {
                    "$month" : "$tov"
                },
                "d" : {
                    "$dayOfMonth" : "$tov"
                }
            }
        },
        "visits" : {
            "$sum" : 1
        }
    }
};

次は DAYS だけを繰り返したいので、EDITは、顧客別、店舗別にグループ化し、その顧客がその店舗に訪問した日数をカウントします。

group2 = {"$group" : 
    {"_id" : {
        "c" : "$_id.c",
        "s" : "$_id.l"
    },
    "totalDays" : {
        "$sum" : 1
    }
} };

次に、同じ顧客が複数日にわたって同じ店舗に複数回訪問した上記のレコードのみを含める必要があります。

match = { "$match" : { "totalDays" : { "$gt" : 1 } } };

サンプル データ セットと、上記のパイプライン操作を使用したこの集計の結果を次に示します。

> db.visits.find({},{_id:0,purchases:0}).sort({location:1, clientId:1, tov:1})
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-01T20:00:00Z") }
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 1, "location" : "l1", "tov" : ISODate("2013-01-03T20:00:00Z") }
{ "clientId" : 2, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 3, "location" : "l1", "tov" : ISODate("2013-01-01T21:00:00Z") }
{ "clientId" : 3, "location" : "l1", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 1, "location" : "l2", "tov" : ISODate("2013-01-01T23:00:00Z") }
{ "clientId" : 3, "location" : "l2", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 3, "location" : "l2", "tov" : ISODate("2013-01-02T21:00:00Z") }
{ "clientId" : 1, "location" : "l3", "tov" : ISODate("2013-01-03T20:00:00Z") }
{ "clientId" : 2, "location" : "l3", "tov" : ISODate("2013-01-04T20:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T20:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T21:00:00Z") }
{ "clientId" : 4, "location" : "l3", "tov" : ISODate("2013-01-04T22:00:00Z") }

> db.visits.aggregate(group1, group2, match)
{
    "result" : [
    {
        "_id" : {
            "c" : 3,
            "s" : "l1"
        },
        "totalDays" : 2
    },
    {
        "_id" : {
            "c" : 1,
            "s" : "l1"
        },
        "totalDays" : 2
    }
    ],
    "ok" : 1
}
于 2013-05-13T17:00:26.333 に答える