【问题标题】:Store and query Fields with Redis使用 Redis 存储和查询字段
【发布时间】:2018-09-27 06:11:53
【问题描述】:

我想用这些字段在 redis 中存储数千条记录:

User_id: int64;
latitude: float;
longitude: float;
age: int32;
height: int32

稍后我想检索所有与 (lat:x,lng:y) 年龄在 30 到 40 之间的人接近的user_id p>

redis 可以做到这一点吗?否则有哪些memory database 列表可以允许这样做?

【问题讨论】:

  • 如果您想要一个真正高效的系统,也许可以使用专用的空间索引,例如 RTree。一个有用的实现可能类似于toblerity.org/rtree。有趣的是,您可以将年龄和身高映射为数据中的维度,并运行多维度查询。
  • 感谢 barryhunter,但为什么(还)不存在这样的内存数据库引擎?如果不是完全定向的全文索引,sphinx 可以很好地完成这项工作:(
  • 我不同意 sphinx“完全”面向全文索引,它可能“特别适合”,但它可以做其他查询的类型太好了。 (正如在对您其他线程的回复中所展示的!) - 我将 sphinx 用于许多实际上并非基于“全文”的查询,(包括“在附近查找东西',就像你的例子!!!?)
  • @barryhunter:对不起,我同意你对 sphinx 的看法是正确的,我们在内部使用了很多年,但更新有点复杂(需要合并 xml),我知道它们也是 RT 索引我从不尝试,但无论如何。我不喜欢 sphinx 的另一个想法是我们需要 mysql 客户端 dll,这个 dll 太可怕了 :( 是的,引入了 http json 接口,但看起来从未真正完成(必须是 bson 而不是 json 才能完全优化)。
  • @barryhunter:最后想想,如果我没记错的话,sphinx 不会创建任何索引(文本除外),它会全面扫描内存中的所有行以过滤它们。我想要一个数据库,至少使用一个索引来过滤行+对这个集合的属性的完整扫描

标签: database indexing redis sphinx in-memory-database


【解决方案1】:

希望版主不要给我这个答案,因为它直接回答了“......可以允许这个的内存数据库列表”的问题

您可以考虑我公司的数据库系统,eXtremeDB。请注意,与 redis 不同,它不是开源的,也不是 NoSQL。它是一个内存中的结构化数据 DBMS; SQL 是可选的。

【讨论】:

  • 我会看看它,但我更喜欢开源的东西:(
  • 我应该在我的第一个回复中提到,我们还提供 Perst,一个用于 Java 和 C# 的开源(双许可:GPL 或商业)面向对象的数据库。 Perst 还有一个 R-tree 索引的实现。
【解决方案2】:

如果您使用http://redisearch.io,则可以通过 Redis 高效、轻松地实现这一目标

免责声明:我在 Redis Labs 工作,这里是 RediSearch 的开发地。

如果你已经设置好了,你可以这样做:

127.0.0.1:6379> FT.CREATE myidx SCHEMA coord GEO age NUMERIC height NUMERIC
OK
127.0.0.1:6379> FT.ADD myidx 123 0 FIELDS coord 0,0 age 30 height 40
OK
127.0.0.1:6379> FT.ADD myidx 456 0 FIELDS coord 0.1,0.1 age 30 height 40
OK
127.0.0.1:6379> FT.ADD myidx 789 0 FIELDS coord 0.1,0.1 age 64 height 64
OK
127.0.0.1:6379> FT.ADD myidx 9999 0 FIELDS coord -50,50 age 30 height 40
OK
127.0.0.1:6379> FT.ADD myidx 1000 0 FIELDS coord -50,50 age 64 height 64
OK
127.0.0.1:6379> FT.SEARCH myidx "@coord:[0 0 1 km]"
1) (integer) 1
2) "123"
3) 1) "coord"
   2) "0,0"
   3) "age"
   4) "30"
   5) "height"
   6) "40"
127.0.0.1:6379> FT.SEARCH myidx "@coord:[0 0 100 km]"
1) (integer) 3
2) "789"
3) 1) "coord"
   2) "0.1,0.1"
   3) "age"
   4) "64"
   5) "height"
   6) "64"
4) "456"
5) 1) "coord"
   2) "0.1,0.1"
   3) "age"
   4) "30"
   5) "height"
   6) "40"
6) "123"
7) 1) "coord"
   2) "0,0"
   3) "age"
   4) "30"
   5) "height"
   6) "40"
127.0.0.1:6379> FT.SEARCH myidx "@coord:[0 0 100 km] @age:[30 40]"
1) (integer) 2
2) "456"
3) 1) "coord"
   2) "0.1,0.1"
   3) "age"
   4) "30"
   5) "height"
   6) "40"
4) "123"
5) 1) "coord"
   2) "0,0"
   3) "age"
   4) "30"
   5) "height"
   6) "40"

【讨论】:

  • 感谢这听起来很棒!它们是坐标 GEO 上的索引还是引擎对所有行执行全面扫描?如何更新一行?我没有看到像主键这样的想法?
  • 请为此打开一个新问题,或通过项目网站上的邮件列表联系开发人员。
【解决方案3】:

您可以使用 Redis 的 SORTED SETGEO 命令来实现。

构建索引:

  1. 使用GEO 命令构建位置索引:GEOADD location lng1 lat1 uid1 lng2 lat2 uid2

  2. 使用SORTED SET 命令构建年龄索引:ZADD age 31 uid1 20 uid2

搜索:

  1. 按位置搜索,并将结果保存到临时集:GEORADIUS location lng lat 100 m store location_result
  2. 获取临时集和年龄集的交集,并将结果保存到另一个临时集:ZINTERSTORE location_age_result 2 location_result age WEIGHTS 0 1
  3. 过滤满足年龄条件的用户:ZRANGEBYSCORE location_age_result 30 40

注意:

在使用ZINTERSTORE 命令时,我们使用WEIGHTS 选项只保留年龄作为新集合的分数。

【讨论】:

  • 感谢 for_stack,但我宁愿避免使用可能(取决于查询)巨大、非常巨大的临时集......我什至更愿意进行全面扫描并过滤飞每记录!而且我不仅有年龄,我还有更多的属性,无法为每个人创建索引
  • 据我了解,您不会将临时集下载到客户端,而是将其下载到服务器内部,因此看起来并没有那么糟糕。 MySQL 透明地做这种事情。即使使用 Sphinx,也有这样一个暂时的“内部”结果集(由 max_matches 控制)。 “全表扫描”不适合 REDIS 设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2020-05-10
  • 2018-08-07
  • 1970-01-01
  • 2022-08-05
  • 2015-11-23
  • 2023-03-17
相关资源
最近更新 更多