面试题答案
一键面试- 利用条件限制类decider实现思路:
- 使用Elasticsearch的聚合功能,首先按用户ID进行分组,然后在每个用户组内再按行为类型分组,并统计每种行为类型的发生次数。
- 通过
bucket_selector
这个条件限制类decider来过滤掉行为次数小于等于10次的结果。
- 关键代码片段(以Python的Elasticsearch DSL库为例):
from elasticsearch_dsl import Search, Q
# 创建Search对象
s = Search(using='your_connection', index='your_index')
# 限制时间范围为过去一周
now = datetime.now()
one_week_ago = now - timedelta(days = 7)
s = s.filter('range', 发生时间 = {'gte': one_week_ago, 'lt': now})
# 聚合操作
s.aggs.bucket('by_user', 'terms', field='用户ID') \
.bucket('by_action_type', 'terms', field='行为类型') \
.metric('action_count', 'value_count')
# 使用bucket_selector过滤行为次数大于10次的用户及行为类型
s.aggs['by_user'].bucket('filtered_actions', 'bucket_selector',
buckets_path = {'count': 'by_action_type>action_count'},
script = 'params.count > 10'
)
# 执行搜索
response = s.execute()
# 处理结果
for user_bucket in response.aggregations.by_user.buckets:
user_id = user_bucket.key
for action_bucket in user_bucket.filtered_actions.buckets:
action_type = action_bucket.key
action_count = action_bucket.by_action_type.action_count.value
print(f"用户ID: {user_id}, 行为类型: {action_type}, 行为次数: {action_count}")
在上述代码中:
- 首先通过
range
过滤器限制时间范围。 - 然后通过
terms
聚合分别按用户ID和行为类型进行分组,并使用value_count
统计每种行为类型的发生次数。 - 最后通过
bucket_selector
的script
和buckets_path
来过滤掉行为次数小于等于10次的结果,并输出符合条件的用户ID、行为类型及行为次数。
如果是使用Elasticsearch的原生查询DSL(JSON格式),关键聚合部分如下:
{
"aggs": {
"by_user": {
"terms": {
"field": "用户ID"
},
"aggs": {
"by_action_type": {
"terms": {
"field": "行为类型"
},
"aggs": {
"action_count": {
"value_count": {
"field": "行为类型"
}
}
}
},
"filtered_actions": {
"bucket_selector": {
"buckets_path": {
"count": "by_action_type>action_count"
},
"script": "params.count > 10"
}
}
}
}
}
}
此JSON DSL同样实现了按用户ID分组,再按行为类型分组统计次数,并过滤掉行为次数小于等于10次的结果。