根据文档建立索引,再对索引进行查询获取文档。java
相比与顺序查询:不须要那么多的查询(一个文档一个文档找索引,找到就匹配,须要所有查询,效率很低),并且能够在索引上定位,出如今哪一个文档哪一个地方,支持高亮
Lucene是一个基于Java的全文检索库,能够当作一个持久层框架,与Lucene索引交互mysql
左边保存的是一系列字符串,称为词典。web
每一个字符串都指向包含此字符串的文档(Document)链表(每一个节点还包含文档中出现该索引的频率),此文档链表称为倒排表(Posting List)。spring
若是咱们须要查询包含两个索引的文档,只须要将两个文档共有的文档标号链接成链表
词元
分词器通常使用训练的模型,Word
、IK
等
英文:复数->单数,大写->小写sql
keyword:Java
1. 索引过程:数据库
1) 有一系列被索引文件apache
2) 被索引文件通过语法分析和语言处理造成一系列词(Term)。segmentfault
3) 通过索引建立造成词典和反向索引表。缓存
4) 经过索引存储将索引写入硬盘。app
2. 搜索过程:
a) 用户输入查询语句。
b) 对查询语句通过语法分析和语言分析获得一系列词(Term)。
c) 经过语法分析获得一个查询树。
d) 经过索引存储将索引读入到内存。
e) 利用查询树搜索索引,从而获得每一个词(Term)的文档链表,对文档链表进行交,差,并获得结果文档。
f) 将搜索到的结果文档对查询的相关性进行排序。
g) 返回查询结果给用户。
Solr是Lucene的封装,提供分布式索引,负载均衡查询,配置式使用,基本只支持Java
solr create -c “name”
http://localhost:8983/solr
在其中配置core的field字段、分词器等
name:数据库字段,type:类型,indexed:是否索引,stored:是否缓存,required:是否必须,multiValued:是否多值
<!-- ik分词器 --> <fieldType name="text_ik" class="solr.TextField"> <analyzer type="index"> <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType> <!-- 数据库字段 --> <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> <field name="shoes_name" type="text_ik" indexed="true" stored="true" multiValued="false"/> <field name="price" type="string" indexed="false" stored="true" multiValued="false"/> <field name="details" type="text_ik" indexed="true" stored="true" multiValued="false"/> <field name="url" type="string" indexed="false" stored="true" multiValued="false"/> <field name="pic_url" type="string" indexed="false" stored="true" multiValued="false"/>
当你须要使用web客户端dataimport时,须要添加:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler>
<dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/priceCompare_goods" user="dzou" password="1234"/> <document> <entity name="adidas_goods" transformer="DateFormatTransformer" query="SELECT id,shoes_name,details,pic_url,price,url,store_name,comment,shoes_kind FROM adidas_goods"> <field column="id" name="id"/> <field column="shoes_name" name="shoes_name"/> <field column="price" name="price"/> <field column="details" name="details"/> <field column="url" name="url"/> <field column="pic_url" name="pic_url"/> <field column="shoes_kind" name="shoes_kind"/> <field column="store_name" name="store_name"/> <field column="score" name="score"> </entity> </document> </dataConfig>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-solr</artifactId> </dependency>
@RequestMapping("/add") public String add() throws IOException, SolrServerException { SolrInputDocument doc = new SolrInputDocument(); doc.setField(); doc.setField(); doc.setField(); solrClient.add("",doc); solrClient.commit(""); return ""; }
@RequestMapping("/delete") public String delete(String id) throws IOException, SolrServerException { solrClient.deleteById(id); solrClient.commit(""); return ""; } /** * 删除全部的索引 * @return */ @RequestMapping("deleteAll") public String deleteAll(){ try { solrClient.deleteByQuery("","*:*"); solrClient.commit(""); return "success"; } catch (Exception e) { e.printStackTrace(); } return "error"; }
Map<String, String> map = new HashMap<>(); map.put("set", o.getScore()); SolrInputDocument doc = new SolrInputDocument(); doc.addField("id", o.getId()); doc.addField("score", map); solrClient.add("am_goods", doc); solrClient.commit("am_goods");
/** * 根据id查询索引 * @return * @throws Exception */ @RequestMapping("getById") public String getById() throws Exception { SolrDocument document = solrClient.getById("collection1", "536563"); System.out.println(document); return document.toString(); } /** * 综合查询: 在综合查询中, 有按条件查询, 条件过滤, 排序, 分页, 高亮显示, 获取部分域信息 * @return */ @RequestMapping("search/{keyword}") public String search(@PathVariable("keyword")String keyword){ try { SolrQuery params = new SolrQuery(); //查询条件, 这里的 q 对应 下面图片标红的地方 params.set("q", "shoes_name:"+keyword); //过滤条件 //params.set("fq", "product_price:[100 TO 100000]"); //排序 params.addSort("price", SolrQuery.ORDER.asc); //分页 params.setStart(0); params.setRows(20); //默认域 params.set("df", "shoes_name"); //只查询指定域 //params.set("fl", "id,shoes_name,shoes_kind,shop_name"); //高亮 //打开开关 params.setHighlight(true); //指定高亮域 params.addHighlightField("shoes_name"); //设置前缀 params.setHighlightSimplePre("<span style='color:red'>"); //设置后缀 params.setHighlightSimplePost("</span>"); QueryResponse queryResponse = solrClient.query(params); /*SolrDocumentList results = queryResponse.getResults(); results.forEach(System.out::println);*/ List<HupuGoods> s = queryResponse.getBeans(HupuGoods.class); return s.toString(); } catch (Exception e) { e.printStackTrace(); } return null; }