package com.taro.apise.indexer.core;
import com.taro.apise.indexer.aop.*;
import com.taro.apise.indexer.mapper.IndexDatabaseMapper;
import com.taro.apise.indexer.model.Document;
import com.taro.apise.indexer.model.InvertedRecord;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@Slf4j
@Component
public class IndexManager {
private final IndexDatabaseMapper mapper;
private final ExecutorService executorService;
@Autowired
public IndexManager(IndexDatabaseMapper mapper, ExecutorService executorService) {
this.mapper = mapper;
this.executorService = executorService;
}
// 先批量生成、保存正排索引(单线程版本)
public void saveForwardIndexes(List<Document> documentList) {
// 1. 批量插入时,每次插入多少条记录(由于每条记录比较大,所以这里使用 10 条就够了)
int batchSize = 10;
// 2. 一共需要执行多少次 SQL? 向上取整(documentList.size() / batchSize)
int listSize = documentList.size();
int times = (int) Math.ceil(1.0 * listSize / batchSize); // ceil(天花板): 向上取整
log.debug("一共需要 {} 批任务。", times);
// 3. 开始分批次插入
for (int i = 0; i < listSize; i += batchSize) {
// 从 documentList 中截取这批要插入的 文档列表(使用 List.subList(int from, int to)
int from = i;
int to = Integer.min(from + batchSize, listSize);
List<Document> subList = documentList.subList(from, to);
// 针对这个 subList 做批量插入
mapper.batchInsertForwardIndexes(subList);
}
}
@Timing("构建 + 保存正排索引 —— 多线程版本")
@SneakyThrows
public void saveForwardIndexesConcurrent(List<Document> documentList) {
// 1. 批量插入时,每次插入多少条记录(由于每条记录比较大,所以这里使用 10 条就够了)
int batchSize = 10;
// 2. 一共需要执行多少次 SQL? 向上取整(documentList.size() / batchSize)
int listSize = documentList.size();
int times = (int) Math.ceil(1.0 * listSize / batchSize); // ceil(天花板): 向上取整
log.debug("一共需要 {} 批任务。", times);
CountDownLatch latch = new CountDownLatch(times); // 统计每个线程的完全情况,初始值是 times(一共多少批)
// 3. 开始分批次插入
for (int i = 0; i < listSize; i += batchSize) {
// 从 documentList 中截取这批要插入的 文档列表(使用 List.subList(int from, int to)
int from = i;
int to = Integer.min(from + batchSize, listSize);
Runnable task = () -> { // 内部类 / lambda 表达式里如果用到了外部变量,外部变量必须的 final(或者隐式 final 的变量)
List<Document> subList = documentList.subList(from, to);
// 针对这个 subList 做批量插入
mapper.batchInsertForwardIndexes(subList);
latch.countDown(); // 每次任务完成之后,countDown(),让 latch 的个数减一
};
executorService.submit(task); // 主线程只负责把一批批的任务提交到线程池,具体的插入工作,由线程池中的线程完成
}
// 4. 循环结束,只意味着主线程把任务提交完成了,但任务有没有做完是不知道的
// 主线程等在 latch 上,只到 latch 的个数变成 0,也就是所有任务都已经执行完了
latch.await();
}
@SneakyThrows
public void saveInvertedIndexes(List<Document> documentList) {
int batchSize = 10000; // 批量插入时,最多 10000 条
List<InvertedRecord> recordList = new ArrayList<>(); // 放这批要插入的数据
for (Document document : documentList) {
Map<String, Integer> wordToWeight = document.segWordAndCalcWeight();
for (Map.Entry<String, Integer> entry : wordToWeight.entrySet()) {
String word = entry.getKey();
int docId = document.getDocId();
int weight = entry.getValue();
InvertedRecord record = new InvertedRecord(word, docId, weight);
recordList.add(record);
// 如果 recordList.size() == batchSize,说明够一次插入了
if (recordList.size() == batchSize) {
mapper.batchInsertInvertedIndexes(recordList); // 批量插入
recordList.clear(); // 清空 list,视为让 list.size() = 0
}
}
}
// recordList 还剩一些,之前放进来,但还不够 batchSize 个的,所以最后再批量插入一次
mapper.batchInsertInvertedIndexes(recordList); // 批量插入
recordList.clear();
}
static class InvertedInsertTask implements Runnable {
private final CountDownLatch latch;
private final int batchSize;
private final List<Document> documentList;
private final IndexDatabaseMapper mapper;
InvertedInsertTask(CountDownLatch latch, int batchSize, List<Document> documentList, IndexDatabaseMapper mapper) {
this.latch = latch;
this.batchSize = batchSize;
this.documentList = documentList;
this.mapper = mapper;
}
@Override
public void run() {
List<InvertedRecord> recordList = new ArrayList<>(); // 放这批要插入的数据
for (Document document : documentList) {
Map<String, Integer> wordToWeight = document.segWordAndCalcWeight();
for (Map.Entry<String, Integer> entry : wordToWeight.entrySet()) {
String word = entry.getKey();
int docId = document.getDocId();
int weight = entry.getValue();
InvertedRecord record = new InvertedRecord(word, docId, weight);
recordList.add(record);
// 如果 recordList.size() == batchSize,说明够一次插入了
if (recordList.size() == batchSize) {
mapper.batchInsertInvertedIndexes(recordList); // 批量插入
recordList.clear(); // 清空 list,视为让 list.size() = 0
}
}
}
// recordList 还剩一些,之前放进来,但还不够 batchSize 个的,所以最后再批量插入一次
mapper.batchInsertInvertedIndexes(recordList); // 批量插入
recordList.clear();
latch.countDown();
}
}
@Timing("构建 + 保存倒排索引 —— 多线程版本")
@SneakyThrows
public void saveInvertedIndexesConcurrent(List<Document> documentList) {
int batchSize = 10000; // 批量插入时,最多 10000 条
int groupSize = 50;
int listSize = documentList.size();
int times = (int) Math.ceil(listSize * 1.0 / groupSize);
CountDownLatch latch = new CountDownLatch(times);
for (int i = 0; i < listSize; i += groupSize) {
int from = i;
int to = Integer.min(from + groupSize, listSize);
List<Document> subList = documentList.subList(from, to);
Runnable task = new InvertedInsertTask
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
技术实现:Spring 项目(SSM 框架):展示:http://43.143.77.107:8090 简单介绍:1、主要分为构建索引模块与搜索模块两个部分;2、构建索引采用 Ansj 进行分词后,分别构建正排索 引与倒排索引保存至数据库中用于搜索模块搜索;3、利用 MyBatis SQL 特性动态操作数据库中索引的插入;4、 利用 Parallel Stream 并行执行,提高构建速度;5、利用线程池进行多线程处理提高索引保存速度 6、利用 AOP 切面计算索引保存时间 7、搜索模块利用 HTML+CSS+JS 实现前端搜索功能 8、为索引构建 搜索树 操作方法:1、找到文档中db.sql运行数据库2、下载解压后在indexer模块下src/main/java/com/taro/apise/indexer/路径找到IndexerApplication.java点击运行构建索引3、构建好后在search模块找到SearchApplication.java运行4、浏览器访问:localhost:8090/index.html
资源详情
资源评论
资源推荐
收起资源包目录
API搜索引擎(简单易上手适用于各种课程设计,附带几个测试用例)
展示:http://43.143.77.107:8090 (564个子文件)
0125c74af262c103f3917a628b21dda01c6131 48B
015540b3f25e6d28da3c601bf385136d0e80b1 580B
0256d7437b6f1175798cd03f9bc2584e159def 236B
03b58d99f55086083bd5b4985ab058e2ad49dc 230B
03dd105eabedcc87c03c9cc61203887f0c0eee 246B
0521bcf85940fa7e54c8de07f9c58e2c72cf96 155B
0a08a7a88797ef011a70c3256c114834e396a5 284B
0a2d44aedb316d678b995c0f1c66f0b8cb0ea1 226B
0b06b7050cdf802c31fd58e8bfe9b65543f92f 55B
0e07073017634d1a087b10eb3ebe196415ed82 228B
0e6f26d2b086c8d56b9bc466a2abe9589530ab 240B
0ea86ccbb0dbafa378a097aa44e5d579d42e5b 230B
0f788bb8302954f1d7e8a54182976a66b7c040 62B
0f9ec05e02c6e8109b45cc6a870a416b7d0b87 88B
0fc477e921c4419b708eea33d1c36c94d688f1 221B
10f1f881b71641fa4a1c2012d5ff40066721d0 303B
11b090e98b150d2546da1bb1372fff2f496f56 233B
127c293eb56dbb26c1cc69af4b1a1cd58802ec 210B
13d2b292d379e24470d71282ac8188da639842 562B
13def613e219a944b47f973641c7b0485b04bf 211B
148fd093d21e09e62a208c44ac2729f6e1d8dc 205B
1492dec07e98b10a90d8c89dadf25e3b2684c4 235B
1498fb19d13e15451a40db87be02e1f94a68a1 80B
14c366fccdc85267dd4c714c4da5d1882d3f02 218B
17b87b757ca152896e16e627b718ee4136339b 529B
1865be7a6e38315e75954f25d6b2f309e32926 213B
1909870578f6b8ea95b162325c24954014168b 57B
1948d2f733354a8c719d165b1b5954b01e7706 149B
1b2637baac4b7df5f0f1d0b302a89fb84df50d 494B
1ba2bffea220361cd22c3c01f27603b321e4f5 188B
1d0959f750d15fd42de185cd84131e967c48d3 235B
1df972f4ea9b8eda7a71ca44f466b6fb16e625 46B
1e3b7434d0fb430885c9876780064212646f94 46B
1e407dcf1f7c4b2e4ae5fb2f1a55ccfca14070 45B
1efa7e5a626957fe750e983ff2aed4748cbfd9 238B
213f73868a39471664c431bdb5073055eb36d5 230B
2365b74cd5416f8b8f58e3f75d2a4e282e1b6f 2KB
246ae1cab497ce43d8c6527e4332be42443c2b 245B
26a4b923f244ac3ff06cc88e554439b96d8942 245B
2a60a4c2813356d227a472e6e9e4cbfeda3f02 834B
2b017eda580f993d787c7deffcd3091006b606 235B
2d2c16b0b0541f8dc4dfca0f63e85ade210371 45B
2f139ce25c6f225e0cb5fb199704f51273de00 307B
2ff744cbf47fc2f99696de25ee6dc918eb0a81 245B
3175b91f70f96038ed2592199ec8dfca1c0e77 91B
33e91dca082f144ce9a1753e941839eefb77f4 249B
343ccf09167202bb78ace4f8c0f72bb6aa462c 48B
34aa0538d29343fd8acda7b2cb199efa85e78d 219B
350bd7ae6653dddb8b55b5e015feb5fd87fa48 232B
352135d25aaae75039357dda3f06404fe92ce1 126B
367e75fd8c350c516152bc439026b0147a6b1b 224B
3789a5fb5b30a3435c7a3ab18bb61dc48c838d 2KB
3aebea8b18775db550bed2779138258a7281cf 235B
3bcb29172f47a50b4c4bd6351786b0862c280e 242B
3f388a817f61b8d34b2cb1d290207bb37337ee 182B
3fa188af467e6eaf749e78ef384fd48217270d 218B
3ffb131ceafb74299f52b72919269f4bb73aa5 235B
42b747346f35aa6ebc0807d4fd4d20d5d01362 243B
458319192e815453b5cf03621d9bb969423c5c 231B
45eaaa70993c315df8ffb1e79f91e7b43c4d48 74B
462d9b08de3d45f3506fba99057c6d37d72a97 241B
4897b62ef7e5f2553d69a47780c0287f3a7b9a 79B
4b378bf67580dc814337ab010f7c42e61265c2 772B
4bf7fcd640440a49eb602158547670ef907772 129B
4d50d1bf46d9ee288e923a842a153ca9beeb30 69B
5078321a92ac15b9ae34a060391d17328816e8 227B
50a857d1f0034e3c0b1b21a828f71f3ee21937 221B
5211c4017d56438d2c33428528491ab455b479 163B
524c094c8c0c79fe3c604255c5f110d26cc8df 303B
53d616ccd763173ec7fae07fdf76649579f53c 226B
542c238e637d0f3b8321675235048e8a368e25 218B
5496ff097a7fd9b72025c4acf36cda1416eda3 210B
559c38c7ac0839d9e6bae7f3a603bef666fa4c 239B
55ff5f8118cec853d3fd6a729e6f4e0d6986fe 49B
566f902ff91316723c866194e4eed33c53c136 233B
581a6f5eef96c4979f258063e7c7c8d633f024 250B
582d63039da5a6027d2a662b96b271505e9fed 220B
5904f7e8eaa3e2bcad1eb4cf7bc35a9ee18b36 96B
593055009ef95f37be0a722680aca383d8aff8 222B
59d3afb2da4449370d50eab8cf28796b5e77a8 45B
5a3c0ecfb13084859a2c88dc86e4a904fa6b13 216B
5b089c817b4c5423e4d3f3bed9b065a30b0c61 221B
5c14ba2c6338dc138643eda1c16eb84b5ad674 217B
5cfcef63aeb6c73691f546497af36a69541a4e 227B
5d124498e24134f299703ef2f064cb0d0e0689 215B
5d50544346a88d2c9c9f15874a9061cd7967e9 80B
5e6bd970af21eb036989e99fa6304afa44dc82 4KB
5e7153bd87bd72f62bd354c75e40dbf8fdb3e4 55B
5fb5d88770a6036aa6843326dd9b5323d5ca3f 251B
607a694887d9df7bc03ac8f60308ce8af64dd5 229B
614912cec3db844a1ef501f289f2777945446a 249B
61e3e2ec38242dbdde7fa8b2a215ee6cc3179d 512B
6246cdbd999d1b5f0c2db4d8579f244ccff8db 344B
63be0bde70a8feff7f5a04e71aabffabeff9b6 74B
681bbd4fd71d833bfe20b266ce59527fe59e1d 232B
690e2b9a2dfa27417a1318ede02b56ee76ad0c 45B
6ce15c4e3485cad08fe223e9139cd91c192879 91B
7165cdabe858825492c35b8bf7e67d7c9ddb87 225B
72755fe2f26ee17a0606c188056f94dc1c6e9c 149B
73b414d9898a5fc273175e1bb72b345292a8cb 525B
共 564 条
- 1
- 2
- 3
- 4
- 5
- 6
一哑7
- 粉丝: 414
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0