以下是 pdf-07 内容
增加基于 Lucene 的针对书籍简介的全文搜索功能,用户可以在搜索界面输入搜索关键词,后端通过全文搜索引擎找到书籍简介中包含该关键词的书籍列表。
Lucene 是一个开源的、成熟的全文索引与信息检索(IR)库,采用 Java 实现。信息检索指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。Lucene 可以为 web 程序添加索引和搜索能力,使得可以转换成文本格式的任何数据能够被搜索。
主要分为索引组件和搜索组件两个步骤。
- 索引组件 为了快速搜索大量文本,必须将文本内容转换成能够进行快速搜索的格式,从而消除慢速顺序扫描处理所带来的影响,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。Lucene 采用反向索引机制,即维护一个词/短语表。整个索引过程包括:
- 获取内容
- 建立文档
- 文档分析
- 文档索引
- 搜索组件 搜索是在一个索引中查找单词来找出它们所出现的文档的过程。搜索质量主要由查准率和查全率来衡量。查准率用来衡量搜索系统查找相关文档的能力,而查准率用来衡量搜索系统过滤相关文档的能力。
- Analyzer 分析器,将字符串按照某种规则划分成一个个词语,并去除其中的无效词语,例如英文中的 "of",中文中的"的"等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率和提高命中率。
- Document 用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个 Document 形式存储在索引文件中。用户进行搜索,也是以 Document 列表的形式返回。
- Field 一个 Document 可以包含多个信息域,例如一篇文章可以包含"标题"、"正文"、"最后修改时间"等信息域,这些信息域就是通过 Field 在 Document 中存储的。
- Term 搜索的最小单位,表示文档的一个词语。
- Tocken term 的一次出现,包含 term 文本和相应的起止偏移,以及一个类型字符串。一句话中可以出现多次相同的词语,它们都用同一个 term 表示,但是用不同的 tocken,每个 tocken 标记该词语出现的地方。
- Segment 添加索引时并不是每个 document 都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个 segment。
在管理员上传或者更改图书信息时将每本书书籍简介和书籍 id抽出写入一个单独的json文件,并利用 Lucene 为这些 document 建立索引。用户在前端进行全文搜索时,则直接从相应的索引文件中查找并返回书籍列表。
[FilesPositionConfig] 定义程序索引文件接口和文件名生成方式等规范。
public class FilesPositionConfig {
......
public final static String indexPath = "index\\INDEX_PATH\\";
public final static String docsDir = "index\\DOCS_PATH\\";
public final static String docsType = "json";
public static String docsPath(String pathName, String type) {
return docsDir + pathName + "." + type;
};
public static String bookid2filePath(Integer id) {
return docsPath("book-" + id, docsType);
}
}
[ReadWriteFiles] 定义读写 JSON 文件方式,以及创建索引接口。
public class ReadWriteFiles {
/* 创建索引和索引数据之间接口 */
void create_docs_files(Integer id, String description, Boolean update) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("book_id", id);
jsonObject.put("description", description);
String filePath = FilesPositionConfig.bookid2filePath(id);
try {
writeFile(filePath, jsonObject);
String[] args = {"-index", FilesPositionConfig.indexPath, "-docs", FilesPositionConfig.bookid2filePath(id),
update ? "-update" : "-not-update"};
IndexFiles.index_interface(args);
} catch (IOException e) {
e.printStackTrace();
}
}
/* 将 JSON 文件写入 DOCS_PATH */
public static void writeFile(String filePath, JSONObject contents) throws IOException {
FileWriter fw = new FileWriter(filePath);
PrintWriter out = new PrintWriter(fw);
out.write(contents.toJSONString());
fw.close();
out.close();
}
/* 读取 JSON 文件中特定 key 的 value */
public static String readFile(String filePath, String key) throws IOException {
BufferedReader reader = null;
StringBuilder laststr = new StringBuilder();
try {
/* 通过路径获取流文件,这种形式能够确保在以 jar 包形式运行时也可以成功获取到文件 */
InputStream inputStream = new FileInputStream(filePath);
/* 设置字符编码为 UTF-8, 避免读取中文乱码 */
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
/* 通过 BufferedReader 进行读取 */
reader = new BufferedReader(inputStreamReader);
String tempString = null;
while ((tempString = reader.readLine()) != null) laststr.append(tempString);
/* 关闭 BufferedReader */
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
/* 不管执行是否出现异常,必须确保关闭 BufferedReader */
reader.close();
} catch (IOException ignored) {}
}
}
JSONObject jsonObject = JSON.parseObject(laststr.toString());
return jsonObject.get(key).toString();
}
}
[IndexFiles] 为json文件建立索引,沿用老师所给样例。 [SearchFiles] 在建立的索引中进行全文搜索,沿用老师所给样例,增加返回列表。
public static List<Integer> search_interface(String[] args) throws Exception {
...
List<Integer> bookidLIst = doPagingSearch(...)
...
return bookidList;
}
public static List<Integer> doPagingSearch(...) {
...
/* 将书籍 book_id 添加到返回列表中 */
bookidList.add(Integer.parseInt(ReadWriteFiles.readFile(doc.get("path"), "book_id")));
...
}
[BookRepositoryImpl] 在修改书籍方法中添加增加索引步骤,增加全文搜索功能。
/* 修改图书信息 */
public Integer editBookInfo(Book book) {
...
/* 创建书籍信息 docs 并创建相应索引 */
ReadWriteFiles.create_docs_files(book.getId(), book.getIntroduction(), true);
...
}
/* 全文搜索书籍 */
public List<Book> fulltextSearchBook(String text) {
List<Book> bookList = new ArrayList<>();
try {
String[] args = {"-index", FilesPositionConfig.indexPath, "-query", text};
List<Integer> bookidList = SearchFiles.search_interface(args);
for (Integer integer : bookidList) {
Book book = getBookById(integer);
/* 如果该书没有被删除 */
if (book != null && book.getState() == 1) bookList.add(book);
}
} catch (Exception e) {
e.printStackTrace();
}
return bookList;
}
[BookControllerImpl] 增加全文搜索访问接口。
@GetMappint("/book/fulltextSearchBook")
public ResponseEntity<List<Book>> fulltextSearchBook(String searchbookstr) {
return new ResponseEntity<>(bookService.fulltextSearchBook(searchbookstr), HttpStatus.OK);
}
[Home] 增加全文搜索按钮及功能
<template>
<el-menu-item>
<el-switch
v-model="searchtype"
active-text="全文搜索"
inactive-text="普通搜索">
</el-switch>
</el-menu-item>
</template>
export default {
data() {
return {
...
searchtype: true,
}
},
methods: {
/* 根据书名模糊搜索 & 全文搜索 */
searchBook(searchbookstr) {
...
url: this.searchtype === true ? '.../fulltextSearchBook' : '.../searchBookByBookname'
}
}
}
管理员上传/修改书籍信息时增加/修改相应索引。 用户在前端进行全文搜索 后端的全文搜索结果
BookController BookRepositoryImpl FilesPositionConfig ReadWriteFiles IndexFiles SearchFiles
07-searching.pdf https://developer.aliyun.com/article/25770 https://zhuanlan.zhihu.com/p/82483865 https://blog.csdn.net/yyunix/article/details/6887146 https://blog.csdn.net/Peacock__/article/details/84099685
以下是 pdf-08 内容
将全文搜索功能开发并部署为 Web Service。
SOAP(Simple Object Access Protocol) 是一种基于 XML 的 web 服务协议。SOAP 是平台独立的,不依赖于特定的语言。在本项目中,我们使用 JAVA 语言来实现 SOAP web 服务。 SOAP 优缺点
- Ws Security:SOAP 使用 WS Security 作为其安全的标准,安全性较高。
- 语言与平台独立:可以使用多种语言来实现 SOAP web 服务,且可以运行在多种平台上。
- 速度较慢:SOAP 使用 XML 作为数据传输的格式,web 服务每次读取数据时都需要对 XML 进行解析,速度较慢。另外,SOAP 规定了 web 服务需要遵循的许多规范,这导致在传输过程中消耗较多的网络带宽。
- 依赖于 WDSL:除了使用 WSDL外,SOAP 并不提供其他的机制来让其他应用程序发现服务。
[FullTextEndPoint] 参考老师所给代码实现
@Endpoint
public class FulltextEndpoint {
private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service";
private BookRepository bookRepository;
@Autowired
public FulltextEndpoint(BookRepository bookRepository) { this.bookRepository = bookRepository; }
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getFulltextRequest")
@ResponsePayload
public GetFulltextResponse getFulltext(@RequestPayload GetFulltextRequest request) {
GetFulltextResponse response = new GetFulltextResponse();
response.setBookliststr(JSONObject.toJSONString(bookRepository.fulltextSearchBook(request.getText())));
return response;
}
}
[WebServiceConfig] 参考老师上课所给样例实现
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "fulltext")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema fulltextSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("FulltextPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
wsdl11Definition.setSchema(fulltextSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema fulltextSchema() { return new SimpleXsdSchema(new ClassPathResource("fulltext.xsd"));
}
}
[fulltext.xsd] 用于定义和规范参数传递与结果返回形式
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring.io/guides/gs-producing-web-service"
targetNamespace="http://spring.io/guides/gs-producing-web-service" elementFormDefault="qualified">
<xs:element name="getFulltextRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="text" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getFulltextResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="bookliststr" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
使用 Postman 发送 xml 格式的全文搜索请求 SpringBoot 后端显示调用 web service 进行全文搜索 Postman 接收到后端返回的全文搜索结果
CountryConfiguration FulltextClient FulltextEndpoint WebServiceConfig fulltext
[08-web service.pdf](./08-web service.pdf) https://blog.csdn.net/lihao21/article/details/72860623 https://blog.csdn.net/qq_41198459/article/details/100161270