为使用情况分析定义Web服务(桌面应用程序)

时间:2012-10-18 21:15:03

标签: mysql database analytics desktop-application database-normalization

现状
我有一个桌面应用程序(C ++ Win32),我希望匿名跟踪用户的使用情况分析(操作,点击,使用时间等)
跟踪是通过指定的Web服务完成的,用于特定的操作(安装,卸载,点击),所有内容都由我的团队编写并存储在我们的数据库中。

需要
现在我们使用各种数据添加更多使用类型和事件,因此我们需要定义服务 我希望为所有使用类型提供单一通用服务,而不是为每个操作提供大量不同的Web服务,这些服务能够接收不同的数据类型。 例如:

  • “button_A_click”事件,包含1个字段的数据:{window_name(string)}
  • “show_notification”事件,包含3个字段的数据:{source_id(int),user_action(int),index(int)}

问题
我正在寻找一个优雅的&存储这种不同数据的便捷方式,以后我可以轻松查询 我能想到的替代方案:

  • 将每种使用类型的不同数据存储为JSON / XML对象的一个​​字段,但是为这些字段提取数据和编写查询非常困难

  • 为每条记录提供额外的N个数据字段,但这似乎非常浪费。

对于这种模型的任何想法?也许像谷歌分析?请告知......

技术:数据库是在phpMyAdmin下运行的MySQL。

声明: 有一个similar post,它引起我注意DeskMetricsTracker bird等服务,或尝试将谷歌分析嵌入到C ++本机应用程序中,但我宁愿通过自己的服务,并更好地了解如何设计这种模型。

谢谢!

3 个答案:

答案 0 :(得分:2)

这似乎是一个database normalization问题。

我还假设您还有一个名为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表中的相应条目,以将该事件映射到具有适当值的一个或多个属性类型。

示例:

"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                |
+-------------------+----------------+-------------------+

答案 1 :(得分:1)

编辑:Bugger!我读过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
    }
}

我建议添加校验和等安全机制。我想de / serializer在C ++中是非常自定义的,所以也许简单的Base64编码可以做到这一点,它可以作为ascii文本传输。

答案 2 :(得分:0)

你可以为每个事件制作一个表格,你宣布什么是param意味着什么。然后你有一个主表,只输入事件名称和param1等。管理工具非常简单,你可以浏览所有事件,并使用声明每个事件的表来描述它们。例如。对于你的事件button_A_click你插入描述表:

Name                   Param1
button_A_Click    WindowTitle

因此,您可以对活动进行分组或仅选择一个活动..

这就是我解决它的方法。