6

現在の状況
デスクトップアプリケーション(C ++ Win32)を使用しており、ユーザーの使用状況分析(アクション、クリック、使用時間など)を匿名で追跡したい。
追跡は、特定のアクション(インストール、アンインストール、クリック)に対して指定されたWebサービスを介して行われます。 )そしてすべてが私のチームによって書かれ、私たちのDBに保存されます。

必要性
今、さまざまなデータを使用して使用タイプとイベントを追加しているので、サービスを定義する必要があります。
アクションごとに大量の異なるWebサービスを用意するのではなく、すべての使用タイプに対応する単一の汎用サービスを用意して、さまざまなデータ型を受信できるようにします。
例えば:

  • 「button_A_click」イベント、1つのフィールドを持つデータがあります:{window_name(string)}
  • 「show_notification」イベントには、{source_id(int)、user_action(int)、index(int)}の3つのフィールドを持つデータがあります。

質問
この種の多様なデータを保存するためのエレガントで便利な方法を探しているので、後で簡単にクエリを実行できます。
私が考えることができる選択肢:

  • 使用タイプごとに異なるデータをJSON/XMLオブジェクトの1つのフィールドとして保存しますが、データを取得してそれらのフィールドのクエリを作成することは非常に困難です。

  • レコードごとに余分なN個のデータフィールドがありますが、それは非常に無駄に思えます。

この種のモデルのアイデアはありますか?多分グーグルアナリティクスのようなもの?お知らせ下さい...

技術: DBはphpMyAdminで実行されているMySQLです。

免責事項:DeskMetricsTracker birdなどのサービスに注目したり、GoogleアナリティクスをC ++ネイティブアプリケーションに埋め込もうとしたりする同様の投稿 がありますが、私はむしろ自分でサービスを提供したいと考えており、これを設計する方法をよりよく理解しています一種のモデル。

ありがとう!

4

3 に答える 3

2

これは、データベースの正規化の問題のようです。

eventsまた、すべてのイベントが保存される場所という名前のテーブルもあると想定します。

さらに、(簡単にするために)次のデータ属性が必要であると想定します。window_name, source_id, user_action, index

正規化を実現するには、次のテーブルが必要です。

events
data_attributes
attribute_types

各テーブルの構造は次のとおりです。

mysql> describe events;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| event_type | varchar(255)     | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+

mysql> describe data_attributes;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| id              | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| event_id        | int(11)          | YES  |     | NULL    |                |
| attribute_type  | int(11)          | YES  |     | NULL    |                |
| attribute_name  | varchar(255)     | YES  |     | NULL    |                |
| attribute_value | int(11)          | YES  |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+

mysql> describe attribute_types;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| type  | varchar(255)     | YES  |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

アイデアは、あなたが持つことがattribute_typesできるすべての可能なタイプを投入しなければならないということです。次に、新しいイベントごとに、テーブルにエントリを追加し、eventsテーブルに対応するエントリを追加して、data_attributesそのイベントを適切な値を持つ1つ以上の属性タイプにマップします。

例:

"button_A_click" event, has data with 1 field: {window_name "Dummy Window Name"}
"show_notification" event, has data with 3 fields: {source_id: 99, user_action: 44, index: 78}

次のように表されます:

mysql> select * from attribute_types;
+----+-------------+
| id | type        |
+----+-------------+
|  1 | window_name |
|  2 | source_id   |
|  3 | user_action |
|  4 | index       |
+----+-------------+

mysql> select * from events;
+----+-------------------+
| id | event_type        |
+----+-------------------+
|  1 | button_A_click    |
|  2 | show_notification |
+----+-------------------+

mysql> select * from data_attributes;
+----+----------+----------------+-------------------+-----------------+
| id | event_id | attribute_type | attribute_name    | attribute_value |
+----+----------+----------------+-------------------+-----------------+
|  1 |        1 |              1 | Dummy Window Name |            NULL |
|  2 |        2 |              2 | NULL              |              99 |
|  3 |        2 |              3 | NULL              |              44 |
|  4 |        2 |              4 | NULL              |              78 |
+----+----------+----------------+-------------------+-----------------+

このデータのクエリを作成するには、MySQLのCOALESCE関数を使用して、どの列がであるかを確認しなくても値を取得できますNULL

これが私がハックした簡単な例です:

SELECT  events.event_type as `event_type`, 
        attribute_types.type as `attribute_type`, 
        COALESCE(data_attributes.attribute_name, data_attributes.attribute_value) as `value`
FROM    data_attributes,
        events,
        attribute_types
WHERE   data_attributes.event_id = events.id
AND     data_attributes.attribute_type = attribute_types.id

これにより、次の出力が得られます。

+-------------------+----------------+-------------------+
| event_type        | attribute_type | value             |
+-------------------+----------------+-------------------+
| button_A_click    | window_name    | Dummy Window Name |
| show_notification | source_id      | 99                |
| show_notification | user_action    | 44                |
| show_notification | index          | 78                |
+-------------------+----------------+-------------------+
于 2012-10-21T16:30:25.453 に答える
1

編集:バガー!私は C# を読みましたが、あなたは C++ を使用しているようです。申し訳ありません。その原則はまだ役立つ可能性があるため、回答をそのままにしておきます。例は疑似コードと考えてください。

配列で使用するカスタム クラス/構造を定義できます。次に、このデータをシリアル化し、WebService に送信します。例えば:

[Serializable()]
public class ActionDefinition {
    public string ID;
    public ActionType Action; // define an Enum with possible actions
    public List[] Fields;  //Or a list of 'some class' if you need more complex fields
}

List AnalyticsCollection = new List(Of, Actiondefinition);

// ...
SendToWS(Serialize(AnalyticsCollection));

必要な柔軟性を備えて、必要な数のイベントを動的に追加できるようになりました。

サーバー側では、データを簡単に解析できます。

List[of, ActionDefinition] AnalyticsCollection = Deserialize(GetWS());

foreach (ActionDefinition ad in AnalyticsCollection) {
    switch (ad.Action) {
        //.. check for each action type
    }
}

チェックサムなどのセキュリティメカニズムを追加することをお勧めします。デ/シリアライザーはC ++でかなりカスタムになるので、おそらく単純なBase64エンコーディングでうまくいくので、ASCIIテキストとして転送できると思います。

于 2012-10-21T15:05:32.047 に答える
0

どのパラメーターが何を意味するかを宣言する各イベントのテーブルを作成できます。次に、イベント名とparam1などを入力するだけのメインテーブルがあります。管理ツールは非常に簡単です。すべてのイベントを調べ、各イベントが宣言されているテーブルを使用してそれらを記述します。たとえば、イベント button_A_click の場合、説明テーブルに挿入します。

Name                   Param1
button_A_Click    WindowTitle

イベントをグループ化することも、1 つのイベントのみを選択することもできます。

これが私がそれを解決する方法です。

于 2012-10-21T14:59:52.530 に答える