我们有一个应用程序可以捕获用户进行的搜索。由于搜索的性质(我们在几个字符后提供搜索结果)以及人们打字的速度,因此每个搜索/字母都会得到一个日志条目。看起来像这样:
(看起来像是一棵颠倒的圣诞树...)
我们内部需要此数据来计算搜索次数(也称为API调用),但要向客户报告,就“半”查询进行报告并不是很好。
我正在寻找一种方法来将这些行折叠成搜索时间最长/最长时间的行。
有一个陷阱: 一个用户(cid)在一个会话中可以进行1次以上的搜索,但是如果我们查看时间戳,我们可以将其分开。
它必须类似于:
1)对相距不超过2秒的行进行分组
2)按长度(或最后一个)查询顺序以获得最终查询
3)按字词分组,以获取一个字词用于报告的频率的计数
数据为文本:
2019-12-09 2019-12-09 12:58:45 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum cleaner
2019-12-09 2019-12-09 12:58:45 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum cleane
2019-12-09 2019-12-09 12:58:44 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum clean
2019-12-09 2019-12-09 12:58:43 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum clea
2019-12-09 2019-12-09 12:58:43 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum cle
2019-12-09 2019-12-09 12:58:42 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum cl
2019-12-09 2019-12-09 12:58:41 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum c
2019-12-09 2019-12-09 12:58:40 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuum
2019-12-09 2019-12-09 12:58:39 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacuu
2019-12-09 2019-12-09 12:58:38 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vacu
2019-12-09 2019-12-09 12:58:37 5dea585477c94502b52c43fb 92cd6cef-3ed8-4416-ac2d-cc347780b976 search 1 search query vac
2019-12-09 2019-12-09 12:58:15 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue widget
2019-12-09 2019-12-09 12:58:14 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue widge
2019-12-09 2019-12-09 12:58:13 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue widg
2019-12-09 2019-12-09 12:58:12 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue wid
2019-12-09 2019-12-09 12:58:12 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue wi
2019-12-09 2019-12-09 12:58:11 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue w
2019-12-09 2019-12-09 12:58:10 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blue
2019-12-09 2019-12-09 12:58:09 5dea585477c94502b52c43fb 9b41fb1d-59d2-4a12-8974-b2261b2fe484 search 0 search query blu
2019-12-09 2019-12-09 12:57:38 5dea585477c94502b52c43fb f96305d9-590b-4a10-95a2-2d49a9fc63a3 search 1 search query widget
2019-12-09 2019-12-09 12:57:37 5dea585477c94502b52c43fb f96305d9-590b-4a10-95a2-2d49a9fc63a3 search 1 search query widge
2019-12-09 2019-12-09 12:57:36 5dea585477c94502b52c43fb f96305d9-590b-4a10-95a2-2d49a9fc63a3 search 1 search query widg
2019-12-09 2019-12-09 12:57:35 5dea585477c94502b52c43fb f96305d9-590b-4a10-95a2-2d49a9fc63a3 search 1 search query wid
预期结果:
vacuum cleaner 1
blue widget 1
widget 1
答案 0 :(得分:1)
不确定采用基于时间的方法是否最合适,因为无论选择哪个值(例如2秒),用户在键入搜索字词时可能会暂停更长的时间。相反,建议您查找那些本身不是较长的搜索词的子字符串的字符串,该子词稍后在同一会话中输入。这种简单的方法可以通过标准SQL来实现:
SELECT ev,
COUNT(ev) AS ev_count
FROM tbl t1
WHERE
(SELECT COUNT(*)
FROM tbl t2
WHERE t2.cid = t1.cid
AND t2.date <= t1.date
AND t1.ev <> t2.ev
AND t2.ev LIKE CONCAT(t1.ev, '%')) = 0
GROUP BY ev;
一个限制是,例如,如果用户在删除“ r”并正确键入之前错误地键入了“ vacuum cleaner”,则查询将同时返回“ vacuum cleanr”和“ vacuum cleaner”。
See demo here (用MySQL编写,但ClickHouse应该相似)。
答案 1 :(得分:1)
一个看起来像颠倒的圣诞树的日志文件;可以假设最后一个条目在最前面是安全的,因此,如果可以抓住每个组的第一条记录,那么您的问题将得到解决,包括该人拼错了某些东西然后改正的情况。这使得日期和时间与寻找解决方案几乎无关。
假设您的字段“ cid”代表一个搜索,那么这是一个基于您的数据的解决方案,可以准确地产生您的预期结果。输入数据应位于创建为以下内容的名为“ inputTable”的表中:
[resizeImage][3]
在不同的情况下运行以下命令,以查找可能无法正常工作且需要微调的特殊情况。
CREATE TABLE `inputTable` (
`date` datetime DEFAULT NULL,
`ts` datetime DEFAULT NULL,
`tid` varchar(255) DEFAULT NULL,
`cid` varchar(255) DEFAULT NULL,
`xid` varchar(255) DEFAULT NULL,
`xvar` int(11) DEFAULT NULL,
`ec` varchar(255) DEFAULT NULL,
`ea` varchar(255) DEFAULT NULL,
`ev` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
希望这对您有所帮助。
答案 2 :(得分:0)
我想用户不仅可以添加新字符,还可以删除新字符,因此“ xmas tree”规则不适用于每个最终查询。
此查询返回会话中最新的搜索输入(最终查询),可能不是会话中最长的搜索输入。
SELECT search_input, count()
FROM (
SELECT
/* create group of pairs (input_seconds, input_text). */
groupArray((toInt32(ts), ev)) inputs,
/* define the end of each session. */
arrayMap((x, index) -> index = 1 ? 1 : (inputs[index - 1].1 - x.1 > 2 /* 2 is max delay between inputs */ ? index : 0), inputs, arrayEnumerate(inputs)) session_end_points,
/* take the latest input in each session. */
arrayMap(x -> inputs[x].2, arrayFilter(x -> x > 0, session_end_points)) search_inputs,
arrayJoin(search_inputs) search_input
FROM (
/* test data, sorted by DESCending */
SELECT toDateTime(data.1) ts, data.2 cid, data.3 ev
FROM (
SELECT arrayJoin([
('2019-12-09 12:58:55', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'X'),
('2019-12-09 12:58:45', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cleaner'),
('2019-12-09 12:58:45', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cleane'),
('2019-12-09 12:58:44', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum clean'),
('2019-12-09 12:58:43', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum clea'),
('2019-12-09 12:58:43', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cle'),
('2019-12-09 12:58:42', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cl'),
('2019-12-09 12:58:41', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum c'),
('2019-12-09 12:58:40', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum'),
('2019-12-09 12:58:39', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuu'),
('2019-12-09 12:58:38', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacu'),
('2019-12-09 12:58:37', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vac'),
('2019-12-09 12:58:15', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue widget'),
('2019-12-09 12:58:14', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue widge'),
('2019-12-09 12:58:13', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue widg'),
('2019-12-09 12:58:12', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue wid'),
('2019-12-09 12:58:12', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue wi'),
('2019-12-09 12:58:11', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue w'),
('2019-12-09 12:58:10', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blue'),
('2019-12-09 12:58:09', '9b41fb1d-59d2-4a12-8974-b2261b2fe484', 'blu'),
('2019-12-09 12:57:38', 'f96305d9-590b-4a10-95a2-2d49a9fc63a3', 'widget'),
('2019-12-09 12:57:37', 'f96305d9-590b-4a10-95a2-2d49a9fc63a3', 'widge'),
('2019-12-09 12:57:36', 'f96305d9-590b-4a10-95a2-2d49a9fc63a3', 'widg'),
('2019-12-09 12:57:35', 'f96305d9-590b-4a10-95a2-2d49a9fc63a3', 'wid'),
('2019-12-09 12:58:34', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vaX'),
('2019-12-09 12:58:30', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum clean'),
('2019-12-09 12:58:28', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cleane'),
('2019-12-09 12:58:26', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum clean'),
('2019-12-09 12:58:24', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum clea'),
('2019-12-09 12:58:22', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacuum cle'),
('2019-12-09 12:58:15', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vac'),
('2019-12-09 12:58:14', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vacu'),
('2019-12-09 12:58:13', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vac'),
('2019-12-09 12:57:34', '92cd6cef-3ed8-4416-ac2d-cc347780b976', 'vaX')]) data)
ORDER BY ts DESC)
GROUP BY cid)
GROUP BY search_input;
/* Result:
┌─search_input───┬─count()─┐
│ widget │ 1 │
│ vacuum cleaner │ 1 │
│ blue widget │ 1 │
│ vac │ 1 │
│ vaX │ 2 │
│ X │ 1 │
│ vacuum clean │ 1 │
└────────────────┴─────────┘
*/
答案 3 :(得分:0)
问题看起来很老。但是无论如何,我会在这方面分享我的想法,这会帮助某人。
查看日志文件,我发现它缺少用于选择每个客户的最新搜索的 strong组密钥。我从日志中注意到的是,每个客户的每次搜索都在 1分钟内完成。考虑到这一事实,我要做的是获取每个日志条目的timestamp列,在数据集上创建一个新列(假设 timestamp_X )并将其格式化为“ yyyy-MM-dd HH:mm”(因此秒数将被截断或设为00)。所以我有一个强大的分组键集( timestamp_X 和 cid )。
之后,我要使用 timestamp_X 和 cid 将数据集分组,并使用这些组键查询数据集,并通过和获取时间戳上每个分组的最新信息排序。
在T-SQL中,这可以通过WITH语句(公用表表达式)来实现。不确定Clickhouse中的相似之处。但是,我确信上述逻辑可以通过任何SQL语言实现。
希望这对您有所帮助!