springredis:字段范围查询“大于”

bvn4nwqk  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(397)

我正在使用redis来存储一些数据,然后查询它并用最新的信息更新它。
举个例子:
我接收文件数据,其中包含文件的信息和该文件的物理存储位置。
一个机架有多个机架,每个机架可以有多个文件。
每个文件都有一个版本字段,当对文件执行操作时,它会得到更新(递增)。
我计划如何储存?
我需要根据“shelfid+rack id”进行查询——以获取所有文件。
我需要基于“shelfid+rack id+version>xx”进行查询——以获取所有版本高于指定版本的文件。
现在,在SpringDataRedis中可以获得属于一个架子和机架的所有文件。我创建了一个由2个id和基于这个键的后续查询组合而成的键。

  1. private <T> void save(String id, T entity) {
  2. redisTemplate.opsForValue().set(id, entity);
  3. }

但是,如何查询版本字段?我将“version”字段保留为@indexed,但spring存储库查询不起作用。

  1. @RedisHash("shelves")
  2. public class ShelfEntity {
  3. @Indexed
  4. @Id
  5. private String id;
  6. @Indexed
  7. private String shelfId;
  8. @Indexed
  9. private String rackId;
  10. @Indexed
  11. private String fileId;
  12. @Indexed
  13. private Integer version;
  14. private String fileName;
  15. // and other updatable fields
  16. }

存储库方法:

  1. List<ShefEntity> findAllByShelfIdAndRackIdAndVersionGreaterThan(String centerCd,
  2. String floorCd, int version);

上面给出了错误:
java.lang.illegalargumentexception:大于(1):[isgreaterthan,greaterthan]不支持redis查询派生
问。如何基于大于的版本进行查询?
问。spring数据redis甚至可以吗?
问。如果可能的话,我应该如何建模数据(到什么样的数据结构中),以便进行这样的查询?
问。如果我们不使用spring,那么如何在redis中使用rediscli和数据结构呢?
可能是这样的:
<键,键,值>
<shelfid+rackid,版本,文件数据>
我不知道如何在redis中建模?
更新2:一个机架可以有n个机架。一个机架可以有n个文件。每个文件对象都有一个版本。此版本得到更新(o->1->2….)
我只想存储文件的最新版本。所以,如果我们有1个文件对象shelfid-1 rackid-1 fileid-1 version-0。。。。更新版本时。。。我们应该还有一个文件对象。版本-1
我尝试在散列数据结构中将密钥保留为shelfid+rackid的md5散列。但无法查询版本。
我也试过使用zset。
这样保存:

  1. private void saveSet(List<ShelfEntity> shelfInfo) {
  2. for (ShelfEntity item : shelfInfo) {
  3. redisTemplate.opsForZSet()
  4. .add(item.getId(), item, item.getVersion());
  5. }
  6. }

所以,版本就是分数。
但问题是我们不能更新集合的项。因此,对于一个fileid,有多个版本。当我查询时,会得到重复的。
获取代码:

  1. Set<ShelfEntity> objects = (Set<ShelfEntity>) (Object) redisTemplate.opsForZSet()
  2. .rangeByScore(generateMd5Hash("-", shelfId, rackId), startVersion,
  3. Double.MAX_VALUE);

现在,这是一个模拟版本>xx的尝试

5uzkadbs

5uzkadbs1#

为每个创建zset shelfId 以及 rackId 结合
使用两种方法在redis中保存和更新记录

  1. // this methods stores all shelf info in db
  2. public void save(List<ShelfEntity> shelfInfo) {
  3. for (ShelfEntity item : shelfInfo) {
  4. redisTemplate.opsForZSet()
  5. .add(item.getId(), clonedItem, item.getVersion());
  6. }
  7. }

使用update删除旧记录并插入新记录,redis不支持键更新,因为它是一个表,所以需要删除现有记录并添加新记录

  1. public void update(List<ShelfEntity> oldRecords, List<ShelfEntity> newRecords) {
  2. if (oldRecords.size() != newRecords.size()){
  3. throw new IlleagalArgumentException("old and new records must have same number of entries");
  4. }
  5. for (int i=0;i<oldRecords.size();i++) {
  6. ShelfEntity oldItem = oldRecords.get(i);
  7. ShelfEntity newItem = newRecords.get(i);
  8. redisTemplate.opsForZSet().remove(oldItem.getId(), oldItem);
  9. redisTemplate.opsForZSet()
  10. .add(newItem.getId(), newItem, newItem.getVersion());
  11. }
  12. }

从zset中读取带有分数的项目。

  1. List<ShefEntity> findAllByShelfIdAndRackIdAndVersionGreaterThan(String shelfId,
  2. String rackId, int version){
  3. Set<TypedTuple<ShelfEntity>> objects = (Set<TypedTuple<ShelfEntity>>) redisTemplate.opsForZSet()
  4. .rangeWithScores(generateMd5Hash("-", shelfId, rackId), new Double(version),
  5. Double.MAX_VALUE);
  6. List<ShelfEntity> shelfEntities = new ArrayList<>();
  7. for (TypedTuple<ShelfEntity> entry: objects) {
  8. shelfEntities.add(entry.getValue().setVersion( entry.getScore().intValue()));
  9. }
  10. return shelfEntities;
  11. }
展开查看全部

相关问题