您的位置:首页 > 文旅 > 旅游 > 的建站公司_做一个网站最便宜多少钱_今天新闻联播_刷网站百度关键词软件

的建站公司_做一个网站最便宜多少钱_今天新闻联播_刷网站百度关键词软件

2025/3/13 14:54:55 来源:https://blog.csdn.net/qq_34207422/article/details/144748982  浏览:    关键词:的建站公司_做一个网站最便宜多少钱_今天新闻联播_刷网站百度关键词软件
的建站公司_做一个网站最便宜多少钱_今天新闻联播_刷网站百度关键词软件

1、概述

Redis本身并不直接提供自动补全(Auto-Complete)功能,但可以通过合理的数据结构和算法设计实现自动补全的功能。常见的实现方式是使用有序集合(Sorted Set)或前缀树(Trie)结合键值对(String)来存储和查询前缀匹配的词项。

2、方案概述

(1)、数据结构选择

  • 词项存储:使用Redis的Sorted Set来存储所有词项及其权重,以便根据权重排序。
  • 前缀索引:使用Redis的Set类型来存储每个前缀对应的词项列表。

(2)、关键操作

  • 添加词项:将词项插入到Sorted Set中,并为每个前缀创建索引。
  • 查询前缀:根据用户输入的前缀,查找所有匹配的词项,并按权重排序返回结果。

(3)、逻辑梳理

1、添加词项

每次添加一个新词项时,我们需要将其插入到Sorted Set中,并为该词项的所有前缀创建索引。假设我们有一个词项 “apple”,它的权重为 5,我们将执行以下操作:
第一步:插入词项到Sorted Set:

ZADD autocomplete:items 5 "apple"

第二步:拆分词项的前缀,存储前缀到词项的Set集合中

- 前缀"a"SADD autocomplete:index:a apple- 前缀"ap"SADD autocomplete:index:ap apple- 前缀"app"SADD autocomplete:index:app apple- 前缀"appl"SADD autocomplete:index:appl apple- 前缀"apple"SADD autocomplete:index:apple apple
2、查询前缀

当用户输入一个前缀时,我们可以根据该前缀查找所有匹配的词项,并从Sorted Set中获取它们的权重,按权重排序返回结果。假设用户输入了前缀"app",我们将执行以下操作:
第一步:查找匹配的词项

  SMEMBERS autocomplete:index:app

如:以"app"开头的词项,此处返回的Set集合为[“apple”, “application”]。

第二步:获取词项的权重并排序

 ZREVRANGE autocomplete:items 0 -1 WITHSCORES BYSCORE LIMIT 0 10

如:返回 Sorted Set 中的前 10 个词项及其权重,按权重从高到低排序。

3、更新词项权重

为了实现动态更新词项的权重(例如根据用户的点击次数或搜索频率),我们可以使用ZINCRBY命令来增加某个词项的权重。假设我们要将词项"apple"的权重增加 1:

ZINCRBY autocomplete:items 1 "apple"
4、删除词项

如果需要删除某个词项,我们需要从Sorted Set中移除它,并删除所有与该词项相关的前缀索引。假设我们要删除词项"apple":
第一步:Sorted Set 中移除词项:

 ZREM autocomplete:items "apple"

第二步:删除所有前缀索引

- 前缀 "a"SREM autocomplete:index:a apple
- 前缀 "ap"SREM autocomplete:index:ap apple
- 前缀 "app"SREM autocomplete:index:app apple
- 前缀 "appl"SREM autocomplete:index:appl apple
- 前缀 "apple"SREM autocomplete:index:apple apple

3、代码示例

(1)、操作实现类

RedisTemplate配置和序列化注入就不赘述了。
第一:存储目标词项到Zset中。拆分词条成多个索引前缀,创建索引和词条的映射关系,通过Set存储。
第二:根据前缀查询符合预期的词项Set列表,回归到Zset中根据权重重新排序。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Set;
import java.util.List;
import java.util.stream.Collectors;@Service
public class AutocompleteService {private static final String ITEMS_KEY = "autocomplete:items";           // 词条存储(ZSet存储,可以按照分值排序)private static final String INDEX_PREFIX = "autocomplete:index:";         // 索引存储(Set存储,存储所有词条索引和词条的关系)@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 添加词项public void addTerm(String term, double score) {redisTemplate.opsForZSet().add(ITEMS_KEY, term, score);for (int i = 1; i <= term.length(); i++) {String prefix = term.substring(0, i);redisTemplate.opsForSet().add(INDEX_PREFIX + prefix, term);}}// 查询前缀public List<String> searchByPrefix(String prefix, int limit) {Set<Object> terms = redisTemplate.opsForSet().members(INDEX_PREFIX + prefix);if (terms == null || terms.isEmpty()) {return new ArrayList<>();}// 获取词项的权重并排序List<String> sortedTerms = redisTemplate.opsForZSet().reverseRangeByScore(ITEMS_KEY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0, limit).stream().filter(terms::contains).map(Object::toString).collect(Collectors.toList());return sortedTerms;}// 更新词项权重public void updateTermScore(String term, double increment) {redisTemplate.opsForZSet().incrementScore(ITEMS_KEY, term, increment);}// 删除词项public void deleteTerm(String term) {redisTemplate.opsForZSet().remove(ITEMS_KEY, term);for (int i = 1; i <= term.length(); i++) {String prefix = term.substring(0, i);redisTemplate.opsForSet().remove(INDEX_PREFIX + prefix, term);}}
}

(2)、测试类

模拟操作:新增词条、根据输入前缀获取符合的所有词条。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/api/autocomplete")
public class AutoCompleteController {@Autowiredprivate  AutocompleteService autoCompleteService;/*** 添加建议词* @param term 建议词* @param score 权重(可选,默认为 1)* @return 成功消息*/@PostMapping("/add")public String addSuggestion(@RequestParam String term, @RequestParam(required = false, defaultValue = "1.0") double score) {autoCompleteService.addTerm(term, score);return "Suggestion added: " + term;}/*** 获取建议词* @param prefix 用户输入的前缀* @param limit 返回的建议词数量* @return 匹配的建议词列表*/@GetMapping("/suggest")public List<String> getSuggestions(@RequestParam String prefix, @RequestParam(defaultValue = "5") int limit) {return autoCompleteService.searchByPrefix(prefix, limit);}
}

(3)、测试

第一步:添加词条
本例一共添加apple(权重1),ap11(权重1),ap22(权重2),application(权重2)
在这里插入图片描述
可以看到redis中正常存储了Zset的4个词项。
且每一个词项的所有前缀索引也设置了Set集合映射。
在这里插入图片描述

第二步:查询前缀,获取自动补全的词条
查询ap,可以看到能查询到所有匹配的词条,并且是按照权重排序的。
在这里插入图片描述
在查询app,符合的词条只有2个,也是按照权重排序的。
在这里插入图片描述

4、总结

通过合理使用Redis的有序集合和键值对,结合前缀索引和权重排序,可以实现一个自动补全词语的方案。这个方案通常建议用于小型应用,也可以通过分布式架构和Redis模块扩展到大规模应用场景。

5、其他方案实现

  • RediSearch:如果你需要更复杂的自动补全功能(如模糊匹配、分词、全文搜索等),可以考虑使用[RediSearch]模块。RediSearch提供了强大的搜索和自动补全功能,适合构建复杂的应用场景。
  • Elasticsearch:如果你已经在使用Elasticsearch,也可以考虑将自动补全功能集成到Elasticsearch中,利用其强大的全文搜索和自动补全功能。
  • Algolia:如果你不想自己管理基础设施,可以考虑使用Algolia这样的第三方服务,它专门为搜索和自动补全提供了高度优化的解决方案。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com