1.Redisのオートコンプリート機能:
Redisのは私たちが今日ここで強調し、さまざまな機能を実現するために役立つことのRedisの自動補完を実装することである。我々は、ゼロである順序集合を使用して、スコア辞書式順序によって要素の値。その後、我々はできるように、番号は、接頭辞を追加して、道をサフィックス注文する文字に応じて、我々はコンテンツの範囲を検索したい以下、後続の理解のためのコンテンツやアイデアZSETの簡単なソートは次のとおりです。
次のような要素のRedis_concat名ZSETコレクション:
番号 | 数の | スコア |
---|---|---|
1 | A | 0 |
2 | から | 0 |
3 | あいうえお | 0 |
4 | ABEF | 0 |
5 | HJK | 0 |
6 | dbfgll | 0 |
7 | efhuo | 0 |
8 | IOP | 0 |
9 | LKJ | 0 |
10 | さらに出席 | 0 |
ZSETは、我々は、上記見つける必要がある場合は、あなたが見つけることができるはずここでは、辞書によると、昇順に配置されることになる、0の場合は、すべての数値スコア[、AB、ABCDを、ABEF]これらの四つの要素、上記に見えますABは、あなたが[AB、ABCD、ABEF]これらの三つの要素、この時間がある限り、我々は前部要素は、最終的に目的のデータをフィルタリング見つけるための検索条件後の方法を考えるようすることができ、他のと同じ方法を見つけることができるはずです。
- 前にASCII文字が小文字」は、Zは、{遅れています
- だから我々はABに一致する要素を見つけ、および(または「ab`」と「AB {」)にAB {挿入AA {
- 見出さAA {AB {添字と、Zレンジザによって得られたコンテキスト間隔()
- あなたが中国の場合は、保存のために進文字にすべての勧告を支払うサブタイムコードを削除します
2.関連デモシェア
これに基づき、私は独立したフロントと連絡先の名前Redisのプロジェクトの自動補完の使用の後端部を作成し、フロントエンドがJava Springフレームワークを使用してヴュー、バックエンドを使用して、この例では、単一の特徴、良い提案やアイデアがあります与えることができます以下のあなたの注意は、プロジェクトの簡単なプレゼンテーションであるように私は、テキストの最後に追加GitHubのプロジェクトのアドレスで、改善すべきなコメントを残して、そしてより:
次のようにプロジェクトが構成されています。
├─src
│ └─main
│ ├─java
│ │ └─com
│ │ └─home
│ │ ├─config
│ │ ├─constants
│ │ ├─controller
│ │ ├─mapper
│ │ ├─page
│ │ ├─pojo
│ │ └─service
│ │ └─impl
│ ├─resources
│ │ ├─mapper
│ │ └─properties
│ └─webapp
│ └─WEB-INF
│ └─views
│ └─vue
└─target
├─classes
│ ├─com
│ │ └─home
│ │ ├─config
│ │ ├─constants
│ │ ├─controller
│ │ ├─mapper
│ │ ├─page
│ │ ├─pojo
│ │ └─service
│ │ └─impl
│ ├─mapper
│ └─properties
├─generated-sources
│ └─annotations
├─qfang-agent-online-mass-client
│ ├─META-INF
│ └─WEB-INF
│ ├─classes
│ │ ├─com
│ │ │ └─home
│ │ │ ├─controller
│ │ │ ├─mapper
│ │ │ ├─pojo
│ │ │ └─service
│ │ │ └─impl
│ │ └─mapper
│ └─lib
└─redis-web-1.0-SNAPSHOT
├─META-INF
└─WEB-INF
├─classes
│ ├─com
│ │ └─home
│ │ ├─config
│ │ ├─constants
│ │ ├─controller
│ │ ├─mapper
│ │ ├─page
│ │ ├─pojo
│ │ └─service
│ │ └─impl
│ ├─mapper
│ └─properties
├─lib
└─views
Vueの建設段階の:
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
# run unit tests
npm run unit
# run e2e tests
npm run e2e
# run all tests
npm test
に関連する方法Java_Service:
- データ収集の前に1.タブ100、接触はRedisの上に置かれRedisの中に存在しない場合
- 2.符号化方法にあり、使用前にUnicodeエンコーディング、覚えて引き出さ復号化方法を用いた復号に関連するデータ
- 3.接頭辞と接尾辞に削除された関連データを取得した後、誤って削除されている接頭辞と接尾辞のデータと同じクエリを防ぐ、UUIDが追加される(例えばAB&ルックアップ、データ自体に含まAB {等)
- 4又は5は、フロント(コメントの場所を表示するために、本明細書カスタム)への最初の10のデータ依存マッチングの前に得られます
クラスの詳細:
package com.home.service.impl;
import com.home.constants.RedisExpireUtil;
import com.home.mapper.ContactMapper;
import com.home.page.PageObject;
import com.home.page.PageResult;
import com.home.pojo.Contact;
import com.home.service.ContactService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.*;
/**
* 改造为中英文皆可匹配
* 这里全部转为16进制存入到redis中
*/
@Service
public class ContactServiceImpl implements ContactService {
@Autowired
private ContactMapper contactMapper;
@Autowired
private JedisPool jedisPool;
private static final String REDIS_CONCAT = "redis_concat";
private static final String VALID_CHARACTERS = "0123456789abcdefg";
@Override
public Contact selectByPrimaryKey(int i) {
return contactMapper.selectByPrimaryKey(i);
}
/**
* 获取相应的条数的数据
*/
@Override
public PageResult getDateSplitByNum(PageObject pageObject) {
// 获取总条数
int totalCount = contactMapper.getAllCount();
List<Contact> contactList = contactMapper.selectByPageObject(pageObject);
return new PageResult(contactList, totalCount, pageObject);
}
@Override
public List<String> getRelatedWord(String name) {
if (StringUtils.isBlank(name)) {
return null;
}
Jedis jedis = jedisPool.getResource();
if (jedis.exists(REDIS_CONCAT)) {
// 拼接字段
String[] prefixRange = findPrefixRange(coding(name));
// 放入到redis中
List<String> strFinds = putIntoRedisAndFind(prefixRange);
return strFinds;
} else {
// 从数据库放入
transDBToRedis(1, 100);
// 拼接字段
String[] prefixRange = findPrefixRange(name);
// 放入到redis中
List<String> strFinds = putIntoRedisAndFind(prefixRange);
return strFinds;
}
}
/**
* 把数据放入到redis
*
* @return
*/
public void transDBToRedis(int currentPage, int pageSize) {
Jedis jedis = jedisPool.getResource();
PageObject po = new PageObject();
po.setCurrentPage(currentPage);
po.setPageSize(pageSize);
// 1.取出前100条数据
PageResult pageResult = getDateSplitByNum(po);
List<Contact> contactList = (List<Contact>) pageResult.getData();
// 2.放入前100条数据到redis
for (Contact contact : contactList) {
String contactName = coding(contact.getContactName());
if (jedis.zrank(REDIS_CONCAT, contactName) == null) {
jedis.zadd(REDIS_CONCAT, 0D, contactName);
}
}
if (jedis.ttl(REDIS_CONCAT).intValue() == RedisExpireUtil.NEVER_EXPIRE) {
// 放入redis有效期一小时
jedis.expire(REDIS_CONCAT, RedisExpireUtil.ONE_HOUR);
}
}
/**
* 将相关的参数放入redis中
*
* @param prefixRange
*/
private List<String> putIntoRedisAndFind(String[] prefixRange) {
Jedis jedis = jedisPool.getResource();
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
List<String> list = new ArrayList();
try {
jedis.watch(REDIS_CONCAT);
String start = prefixRange[0] + uuid;
String end = prefixRange[1] + uuid;
// 1.放入redis
jedis.zadd(REDIS_CONCAT, 0, start);
jedis.zadd(REDIS_CONCAT, 0, end);
// 2.得到索引的位置
int begin_index = jedis.zrank(REDIS_CONCAT, start).intValue();
int end_index = jedis.zrank(REDIS_CONCAT, end).intValue();
// 3.删除这两个放入的值
jedis.zrem(REDIS_CONCAT, start);
jedis.zrem(REDIS_CONCAT, end);
// 3.因为最多展示5个,所以计算出结束为止
int erange = Math.min(begin_index + 4, end_index - 2);
if(begin_index>erange){
return null;
}
// 4.获得其中的值
Set<String> zrange = jedis.zrange(REDIS_CONCAT, begin_index, erange);
if (zrange == null) {
return null;
}
list.addAll(zrange);
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
String next = it.next();
if (next.indexOf("g") != -1) {
it.remove();
} else {
it.set(decoding(next));//把16进制字符串转换回来
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jedis.unwatch();
}
return list;
}
// 这个方法仅仅适用于匹配英文字符
// public String[] findPrefixRange(String prefix) {
// String start = prefix + '`';
// String end = prefix + '{';
// System.out.println(prefix + " " + start + "---" + end);
// return new String[]{start, end};
// }
//unicode编码
private String coding(String s) {
char[] chars = s.toCharArray();
StringBuffer buffer = new StringBuffer();
for (char aChar : chars) {
String s1 = Integer.toString(aChar, 16);
buffer.append("-" + s1);
}
String encoding = buffer.toString();
return encoding;
}
//unicode解码
private String decoding(String s) {
String[] split = s.split("-");
StringBuffer buffer = new StringBuffer();
for (String s1 : split) {
if (!s1.trim().equals("")) {
char i = (char) Integer.parseInt(s1, 16);
buffer.append(i);
}
}
return buffer.toString();
}
private String[] findPrefixRange(String prefix) {
//查找出前缀字符串最后一个字符在列表中的位置
int posn = VALID_CHARACTERS.indexOf(prefix.charAt(prefix.length() - 1));
//找出前驱字符
char suffix = VALID_CHARACTERS.charAt(posn > 0 ? posn - 1 : 0);
//生成前缀字符串的前驱字符串
String start = prefix.substring(0, prefix.length() - 1) + suffix + 'g';
//生成前缀字符串的后继字符串
String end = prefix + 'g';
return new String[]{start, end};
}
}
3.プロジェクトのgitアドレス
(ありがとう、ああのサポートのようなポイントの星を忘れないでください!)