我有数以百万计的项目按预先计算的分数排序。每个项目都有许多布尔属性。假设总共有大约一万个可能的属性,每个项目都有十几个。
我希望能够实时(几毫秒)请求给定的前 n 个项目〜任何属性组合。
你会推荐什么解决方案?我正在寻找极具可扩展性的东西。
---
我们目前正在研究mongodb和数组索引,您是否看到任何限制?
- SolR 是一种可能的解决方案,但我们不需要文本搜索功能。
如果您像这样存储对象,Mongodb 可以处理您想要的
{ score:2131, attributes: ["attr1", "attr2", "attr3"], ... }
然后下面的查询将匹配所有具有att1和attr2的项目
c = db.mycol.find({ attributes: { $all: [ "attr1", "attr2" ] } })
但这不匹配
c = db.mycol.find({ attributes: { $all: [ "attr1", "attr4" ] } })
查询返回一个游标,如果您希望对该游标进行排序,则只需将排序参数添加到查询中,如下所示
c = db.mycol.find({ attributes: { $all: [ "attr1", "attr2" ] }}).sort({score:1})
查看高级查询以了解可能的情况。
适当的索引可以设置如下
db.mycol.ensureIndex({attributes:1, score:1})
您可以使用获取性能信息
db.mycol.find({ attributes: { $all: [ "attr1" ] }}).explain()
Mongo 解释了扫描了多少对象、操作花费了多长时间以及其他各种统计数据。
这正是Mongo可以处理的。您的属性是布尔类型的事实在这里有所帮助。下面列出了一个可能的模式:
[
{
true_tags:[attr1, attr2, attr3, ...],
false_tags: [attr4, attr5, attr6, ...]
},
]
然后我们可以索引true_tags和false_tags。并且使用 $in, $all, ... 查询运算符进行搜索应该是有效的。
Redis 将是一个完美的候选者
Redis 有一个内置的数据结构,您可以从它开始:Sorted Set
=> 排序集的每个成员都与分数相关联。例如,可以使用ZRANGEBYSCORE按分数排名:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
我鼓励您查看 Sorted Set命令并了解 Redis,因为您的问题(如前所述)要求它。您当然可以在单个 Set 元素中保留任意数量的属性。
至于 MongoDB,既然您提到了数百万,除非您可以弯曲增量查询来解决您的问题,否则我不会期望亚秒级的响应。
正如@nickdos 提到的,Solr Relevancy 是一个非常强大的功能,但是属性的数量将是一个问题,因为它需要将所有这些属性保存在每个项目的内存中。虽然每个人打一打可能没那么糟糕 => 试试看。