原标题:开发人员如何快速定制化实现一个基于Solr的搜索引擎

Solr实现全文搜索

Solr

Apache Solr特点

搜索引擎

搜索引擎组件

搜索引擎工作流程

分词技术

中文分词算法

基于字符串匹配

基于统计及机器学习的分词方式

IKAnalyzer

部署Solr并安装IKAnalyzer

Solr分析功能

修改managed-schema配置业务系统字段

复制配置到容器

重启容器

SpringBoot整合Solr

创建搜索服务接口

创建搜索服务提供者

创建搜索服务消费者

Solr

Solr是一个可扩展的,可部署,搜索,存储引擎,优化搜索大量以文本为中心的数据库Solr是开源搜索平台,用于构建搜索应用程序建立在Lucene(全文搜索引擎)之上Solr是企业级的,快速的和高度可扩展的,使用Solr构建的应用程序可以提供高性能,但是非常复杂Solr可以和Hadoop一起使用:由于Hadoop处理大量数据,Solr可以从大的数据源中找到所需信息.Solr不仅限于搜索,也可以用于存储.和其它NoSQL数据库一样,是一种非关系数据存储和处理技术

Apache Solr特点

Solr是Lucene的Java API包装,使用Solr,就可以使用Lucene的所有功能

RESTful API: 要与Solr通信,可以使用RESTful服务与Solr通信,可以使用XML,JSON,CSV等格式的文件作为输入文档,并以相同的文件格式获取结果

全文搜索: Solr提供了全文搜索所需的所有功能:令牌,短语,拼写检查,通配符,自动完成

企业准备: 根据企业或组织的需要,Solr可以部署在任何类型的系统:独立,分布式,云

灵活可扩展: 通过扩展Java类并进行相关配置,可以定制Solr组件

NoSQL数据库: Solr可以用作大数量级的NoSQL数据库,可以沿着集群分布搜索任务

搜索引擎

搜索引擎:搜索引擎是庞大的互联网资源数据库,如网页,新闻组,程序,图像等有助于在网上定位信息用户可以通过以关键字或短语的形式将查询传递到搜索引擎中来搜索信息,然后搜索引擎搜索其数据库并向用户返回相关链接

搜索引擎组件

搜索引擎有三个组件:

Web爬虫: 一个收集网络信息的软件组件

数据库: Web上的所有信息都存储在数据库中,包含大量的Web资源

搜索接口: 这个组件是用户和数据库之间的接口,帮助用户搜索数据库

搜索引擎工作流程

获取原始内容: 任何搜索应用程序的第一步是收集要进行搜索的目标内容

构建文档: 从原始内容构建文档,让搜索应用程序可以很容易的理解和解释

分析文档: 在索引开始之前,将对文档进行分析

索引文档: 当文档被构建和分析后,下一步是对文档建立索引,以便可以基于特定键而不是文档的全部内容来检索该文档.索引类似于在书开始页或末尾处的目录索引,其中常见单词以页码显示,使得这些单词可以快速追踪,而不是搜索整本书

用于搜索的用户接口: 当索引数据库就绪,应用程序就可以执行搜索操作.为了帮助用户进行搜索,应用必须提供用户接口,用户可以在用户接口中输入文本并启动搜索过程

构建查询: 当用户做出搜索文本的请求,应用程序应该使用该文本准备查询对象,然后可以使该查询对象来查询索引数据库以获得相关细节

搜索查询: 使用查询对象,检查索引数据库以获取相关详细信息和内容文档

渲染结果: 当收到所需结果,应用程序应决定如何使用用户界面向用户显示搜索结果

分词技术

分词技术: 搜索引擎针对用户提交查询的关键词串进行的查询处理后,根据用户的关键词串用各种匹配方法进行分词的一种技术

中文分词算法

基于字符串匹配

基于字符串匹配:即扫描字符串,如果发现字符串的子串和词相同,就算匹配这类分词通常会加入一些启发式规则:正向/反向最大匹配,长词优先等

基于字符串匹配算法优点:速度快都是O(n)时间复杂度实现简单效果尚可

基于字符串匹配算法缺点:对歧义和未登录词处理不好

ikanalyzer,paoding等就是基于字符串匹配的分词

基于统计及机器学习的分词方式

基于统计及机器学习的分词方式:基于人工标注的词性和统计特征,对中文进行建模. 即根据观测到的数据(标注好的语料)对模型参数进行估计.即 训练在分词阶段再通过模型计算各种分词出现的概率,将概率最大的分词结果作为最终结果常见的序列标注模型:HMM,CRF

基于统计及机器学习的分词方式优点:可以很好地处理歧义和未登录问题效果比基于字符串匹配算法更好

基于统计及机器学习的分词方式缺点:需要大量的人工标注数据较慢的分词速度

IKAnalyzer

IKAnalyzer是一个开源的,基于Java语言开发的轻量级中文分词工具包

基于文本匹配,不需要投入大量的人力进行训练和标注

可以自定词典,方便加入特定领域的词语,能分出多粒度的结果

部署Solr并安装IKAnalyzer

创建/usr/local/docker/solr/ikanalyzer目录

/usr/local/docker/solr 用于存放docker-compose.yml配置文件

/usr/local/docker/solr/ikanalyzer 用于存放Dockerfile镜像配置文件

docker-compose.yml

version: '3.1'

services:

solr:

build: ikanalyzer

restart: always

container_name: solr

ports:

- 8983:8983

volumes:

- ./solrdata:/opt/solrdata

Dockerfile(在/usr/local/docker/solr/ikanalyzer中需要有文件:ik-analyzer-solr5-5.x.jar,solr-analyzer-ik-5.1.0.jar,ext.dic,stopword.dic,IKAnalyzer.cfg.xml,managed-schema)

FROM solr

# 创建Core

WORKDIR /opt/solr/server/solr

RUN mkdir ik_core

WORKDIR /opt/solr/server/solr/ik_core

RUN echo 'name=ik_core' > core.properties

RUN mkdir data

RUN cp -r ../configsets/sample_techproducts_configs/conf/ .

# 安装中文分词

WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF/lib

ADD ik-analyzer-solr5-5.x.jar .

ADD solr-analyzer-ik-5.1.0.jar .

WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF

ADD ext.dic .

ADD stopword.dic .

ADD IKAnalyzer.cfg.xml .

# 增加分词配置

COPY managed-schema /opt/solr/server/solr/ik_core/conf

WORKDIR /opt/solr

构建镜像: 在/usr/local/docker/solr中执行命令

docker-compose up -d

Solr分析功能

修改managed-schema配置业务系统字段

Solr中自带的相同字段无需再添加,其它字段需要手动添加Solr字段(通过编辑managed-schema配置文件来手动添加Solr字段)

复制配置到容器

docker cp managed-schema solr:/opt/solr/server/solr/ik_core/conf

重启容器

docker-compose restart

在Solr的Web界面可以进行CRUD操作

SpringBoot整合Solr

创建搜索服务接口

创建myshop-service-search-api项目,该项目只负责定义定义接口

pom.xml

4.0.0

com.funtl

myshop-dependencies

1.0.0-SNAPSHOT

../myshop-dependencies/pom.xml

myshop-service-search-api

jar

在项目中创建SearchService接口

package com.oxford.myshop.service.search.api;

public interface SearchService {

List search(String query,int page,int rows);

}

创建TbItemResult用于返回Solr结果集

package com.oxford.myshop.service.search.domain;

import java.io.Serializable;

public class TbItemResult implements Serializable {

private long id;

private long tbTtemCid;

private String tbItemCname;

private String tbItemTitle;

private String tbItemSellPoint;

private String tbItemDesc;

public long getId(){

return id;

}

public void setId(long id){

this.id=id;

}

public long getTbTtemCid(){

return tbTtemCid;

}

public void setTbTtemCid(long tbTtemCid){

this.tbTtemCid=tbTtemCid;

}

public String getTbItemCname(){

return tbItemCname;

}

public void setTbItemCname(String tbItemCname){

this.tbItemCname=tbItemCname;

}

public String getTbItemTitle(){

return tbItemTitle;

}

public void setTbItemTitle(String tbItemTitle){

this.tbItemTitle=tbItemTitle;

}

public String getTbItemSellPoint(){

return tbItemSellPoint;

}

public void setTbItemSellPoint(String tbItemSellPoint){

this.tbItemSellPoint=tbItemSellPoint;

}

public String getTbItemDesc(){

return tbItemDesc;

}

public void setTbItemDesc(String tbItemDesc){

this.tbItemDesc=tbItemDesc;

}

}

创建搜索服务提供者

创建myshop-service-search-provider服务提供者项目

MyShopServiceSearchProviderApplication

package com.oxford.myshop.service.search.provider;

@EnableHystrix

@EnableHystrixDashboard

@SpringBootApplication(scanBasePackages="com.oxfrod.myshop")

@MapperScan(basePackages="com.oxford.myshop.service.search.provider.mapper")

public class MyShopServiceSearchProviderApplication {

public static void main(String[] args) {

SpringApplication.run(MyShopServiceSearchProviderApplication.class,args);

Main.main(args);

}

}

在项目中创建TbItemResultMapper接口用于查询MySQL中的数据,用于插入到Solr数据库中

package com.oxford.myshop.service.search.provider.mapper;

@Respository

public interface TbItemResultMapper {

List selectAll();

}

Spring的四大注解:

1. @Controller

2. @Service

3. @Component

4. @Repository

在resource中创建mapper包用于创建TbContentCategoryMapper.xml

select

a.id,

a.title as tb_item_title,

a.sell_point as tb_item_sell_point,

a.cid as tb_item_cid,

b.name as tb_item_cname,

c.item_desc as tb_item_desc

from

tb_item as a

left join tb_item_cat as b

on a.cid=b.id

left join tb_item_desc as c

on a.id=c.item_id

初始化Solr:

public void initSolr() {

List tbItemResult=tbItemResultMapper.selectAll();

try{

SolrInputDocument document=null;

for(TbItemResult tbItemResult:tbItemResults){

document=new SolrInputDocument();

document.addFiled("id",tbItemResult.getId());

document.addFiled("tb_item_cid",tbItemResult.getTbItemCid());

document.addFiled("tb_item_cname",tbItemResult.getTbItemCname());

document.addFiled("tb_item_title",tbItemResult.getTbItemTitle());

document.addFiled("tb_item_sell_point",tbItemResult.getTbItemSellPoint());

document.addFiled("tb_item_desc",tbItemResult.getTbItemDesc());

solrClient.add(document);

solrClient.commit();

}

}catch(SolrServerException e){

e.printStackTrace();

}catch(IOException e){

e.printStackTrace();

}

}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

搜索Solr:

public void searchSolr(){

SolrQuery query=new SolrQuery();

// 设置查询条件

query.setQuery("手机");

// 分页查询

query.setStart(0);

query.setRows(10);

// 设置查询的默认域

query.set("df","tb_item_keywords");

// 设置高亮显示

query.setHighlight(true);

query.addHighlightField("tb_item_title");

query.setHighlightSimplePre("");

query.setHighlightSimplePost("");

// 开始查询

try{

QueryResponse queryResponse=solrClient.query(query);

SolrDocumentList results=queryResponse.getResults();

// 获取高亮

Map>> highlighting=queryResponse.getHighlighting();

for(SolrDocument result:results){

List strings=highlighting.get(result.get("id")).get(result.get("tb_item_title"))

if(strings!=null&&strings.size()>0){

String title=strings.get(0);

System.out.println(title);

}

}

}catch(SolrServerException e){

e.printStackTrace();

}catch(IOException e){

e.printStackTrace();

}

}

创建SearchServiceImpl实现SearchService接口

package com.oxford.myshop.service.search.provider.api.impl;

@Service(version="${services.versions.search.v1}")

public class SearchServiceImpl implements SearchService{

@Autowired

private SolrClient solrClient;

@Override

public List search(String query,int page,int rows){

List searchResults=Lists.newArrayList();

SolrQuery query=new SolrQuery();

// 设置查询条件

query.setQuery("手机");

// 分页查询

query.setStart((page-1)*rows);

query.setRows(rows);

// 设置查询的默认域

query.set("df","tb_item_keywords");

// 设置高亮显示

query.setHighlight(true);

query.addHighlightField("tb_item_title");

query.setHighlightSimplePre("");

query.setHighlightSimplePost("");

// 开始查询

try{

QueryResponse queryResponse=solrClient.query(query);

SolrDocumentList results=queryResponse.getResults();

// 获取高亮

Map>> highlighting=queryResponse.getHighlighting();

for(SolrDocument solrDocument:solrDocuments){

TbItemResult result=new TbResult();

result.setId(Long.parseLong(String.valueOf(solrDocument.get("id"))));

result.setTbItemCid(Long.parseLong(String.valueOf(solrDocument.get("tb_item_cid"))));

result.setTbItemCname((String)solrDocument.get("tb_item_cname"));

result.setTbItemTitle((String)solrDocument.get("tb_item_title"));

result.setTbItemSellPoint((String)solrDocument.get("tb_item_sell_point"));

result.setTbItemDesc((String)solrDocument.get("tb_item_desc"));

String tbItemTitle="";

List list=highlighting.get(result.get("id")).get(result.get("tb_item_title"))

if(list!=null&&lsit.size()>0){

String title=list.get(0);

}else{

tbItemTitle=(String)solrDocument.get("tb_item_title");

}

result.setTbItemTitle(tbItemTitle);

searchResults.add(result);

}

}catch(SolrServerException e){

e.printStackTrace();

}catch(IOException e){

e.printStackTrace();

}

return searchResults;

}

}

创建搜索服务消费者

创建搜索服务消费者myshop-service-search-consumer对Solr数据库中的数据进行检索

MyShopServiceSearchConsumerApplication

package com.oxford.myshop.service.search.consumer;

@EnableHystrix

@EnableHystrixDashboard

@SpringBootApplication(scanBasePackages="com.oxford.myshop",exclude=DataSourceAutoConfiguration.class)

public class MyShopServiceSearchConsumerApplication{

public static void main(String[] args){

SpringApplication.run(MyShopServiceSearchConsumerApplication.class,args);

Main.main(args);

}

}

SearchController

package com.oxford.myshop.service.search.consumer.controller;

@RestController

public class SearchController{

@Reference(version="${services.versions.search.v1}")

private SearchService searchService;

@RequestMapping(value="search/{query}/{page}/{rows}",method=RequestMethod.GET)

public List search(

@PathVariable(required=true) String query,

@PathVariable(required=true) int page,

@PathVariable(required=true) int rows

){

return searchService.search(query,page,rows)

}

}

责任编辑:

solr是c语言开发的吗,开发人员如何快速定制化实现一个基于Solr的搜索引擎相关推荐

  1. 被定制化开发坑惨了的IT人,不是所有的报表都能满足老板的需求

    下面是一个IT人真实的经历: 老K所在的IT部门是公司近几年才建立起来的,架构非常简单,老K和几个同事负责做系统开发.系统优化和系统管理,比如OA.ERP.BI系统等,另外两个小组做运维工作和专门的产 ...

  2. 组件化开发之-我们有什么必要使用组件化开发?

    原创 2016-05-19 背景介绍: 首先简单说一下为什我会写这篇文章呢? 源于今天讨论,提到这个组件化开发和以前没有多大区别,都需要合作编码,共同开发某些相同模块,本来之前都是按照模块划分来开发的 ...

  3. harmonyos上的程序用什么语言写,HarmonyOS应用开发 — HelloWorld应用开发E2E体验

    感谢关注HarmonyOS,为了便于大家学习特将鸿蒙2.0基础教学内容整理如下: 1.HarmonyOS应用开发-视频播放 https://developer.huawei.com/consumer/ ...

  4. android studio scala插件,Scala 语言开发Andorid ,开发环境的搭建(一)

    Scala 语言开发Andorid ,开发环境的搭建 厌倦 Java 繁琐的语法,为了更优雅的开发 Android 程序,Scala 代替 Java 是一个不错的尝试. 开发前可以学习 Scala 的 ...

  5. 基于c语言的linux嵌入式开发入门

    前言 本文主要包含,c语言基本结构与语法.make及makefile的使用.main函数参数与返回值的说明.标准输入.输出.错误流的介绍以及linux管道的应用. 语言数据类型 联合体也有翻译为共用体 ...

  6. c# 无法加载oraops.dll_Robotstudio软件二次开发:基于C#语言的Smart组件开发基础

    Robotstudio软件除了支持Add-Ins插件的二次开发以外,还支持Smart组件的二次开发.开发语言同样是基于.NET框架的C#语言或VB语言.Smart组件是Robotstudio软件中实现 ...

  7. 【转载】solr教程,值得刚接触搜索开发人员一看

    转载:http://blog.csdn.net/awj3584/article/details/16963525 Solr调研总结 开发类型 全文检索相关开发 Solr版本 4.2 文件内容 本文介绍 ...

  8. python常用的开发环境包括_Python语言主要包括哪些集成开发环境?_学小易找答案...

    [填空题]Python的标准随机数生成器模块是 [简答题]Why does critical thinking matter? [简答题]采集瓶子的外形进行创意设计 用点.线.面进行装饰填充 A4纸手 ...

  9. C语言到嵌入式Linux开发项目指导

    C语言到嵌入式Linux开发项目指导 第一阶段C语言 1.常量与变量,数据类型,数据类型转换,数据输入与输出: 2.C语言运算符,C语言操作符,C语言表达式,表达式优先级: 3.C语言流程控制,分支, ...

  10. 考试君 - 基于.NET 5语言的Furion框架开发在线考试系统

    简介: 考试君 - 基于.NET 5语言的Furion框架开发在线考试系统 网盘下载地址: http://kekewl.net/GiRBtDuKMeP0 图片:

最新文章

  1. 内网穿透工具nps和frp
  2. swagger注解说明_swagger2常用注解说明
  3. JVM学习笔记之-拉圾回收概述,垃圾回收相关算法
  4. 片源系统服务器,OUO NAS10主控界面评测
  5. TensorFlow模型保存和提取方法(含滑动平均模型)
  6. php urlencode 大写,HttpUtility.UrlEncode 编码输出的字母替小写,怎样改成大写呢
  7. Vue中解决移动端点击300毫秒延迟的问题
  8. java 1.6 jdk 64_jdk 1.6 64位官方下载|Java JDK(Java SE Development Kit) 1.6 64位版 - 121下载站...
  9. Android 启动模拟器是出现 Failed to allocate memory 8 错误提示的原因及解决办法
  10. GO及其LiteIDE踩坑
  11. spring框架对jdk版本要求
  12. CSGO中最新骗术!新老玩家须知-CSGO防骗指南
  13. 基于双边滤波的改进型Canny算法边缘检测冠状动脉CT图像
  14. 真无线蓝牙耳机哪个音质最好?2021入门级蓝牙耳机排行榜!
  15. 2014年牡丹江现场赛打铁记
  16. 拜登签署芯片法案后,英特尔股票的前景如何?
  17. 【Linux\云服务器】CentOS 7.2 64位 可视化桌面的安装与卸载
  18. stm32 spi nss硬件模式配置参考程序
  19. matlab导出dat,matlab如何生成数据dat文件
  20. 误删的文件,回收站没有怎么恢复?

热门文章

  1. 怎样区分现代艺术和幼儿涂鸦
  2. 孙鑫VC学习笔记:第十六讲 (二) 利用关键代码段实现线程间的同步
  3. java 修改final_Java反射有效修改final属性值
  4. 拓端tecdat|Python用ARIMA和SARIMA模型预测销量时间序列数据
  5. 拓端tecdat|R语言进行相关矩阵分析及其网络可视化
  6. 拓端tecdat|Stata 中Mata的st_view函数 - 小心使用!
  7. C++概述部分内容记录
  8. manjaro linux下查看硬件温度
  9. jQuery学习笔记04
  10. keras.preprocessing.image函数比较