1. 1SolrCore的配置
  2. a)schma.xml文件
  3. b)配置中文分析器
  4. 2、配置业务域和批量索引导入
  5. a)配置业务域
  6. b)批量索引导入
  7. c)Solrj复杂查询(用Query页面复杂查询、用程序实现)
  8. 3、京东案例(简单的站内搜索实现)
  9. 2.SolrCore的配置(重点)
  10. SolrCore的运行由两个重要的配置文件做指导,一个是solrconfig.xml,一个是schema.xml
  11. 1solrconfig.xml配置
  12. 依赖包、数据目录和请求处理器(/select,/update。。。)等,这是SolrCore的核心配置文件。之前已经介绍过了。
  13. 2schema.xml配置:
  14. 主要是Field域的配置,SolrField的使用必须先配置然后使用,不能在代码中直接new
  15. 2.1.schema.xml
  16. 域的配置包括:普通业务域(field)、动态域(dynamicField)、拷贝域(copyField)、唯一主键域(uniqueKey)、域类型 (fieldType)。
  17. SolrCore本身自带了一些业务域的配置和域类型的定义,但就像MySQL数据库刚创建完就会有一个默认的mysql数据库一样,实际业务中这些自带的配置都没法使用,所以大概看一下就可以忽略掉。
  18. 在实际项目中都是我们自己根据业务需求定义自己的业务域。
  19.  
  20. 2.1.1.field
  21. <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
  22.  
  23. name:域的名称
  24. type:域的类型
  25. indexed:是否索引
  26. stored:是否存储
  27. required:是否必须
  28. multiValued:是否是多值,存储多个值时设置为truesolr允许一个Field存储多个值,比如存储一个用户的好友id可以是多个,商品的图片url可以是多个,这些多个值可以存储在一个field域中。
  29. 注意:配置上面似乎缺少一个【是否分词】的配置属性,是因为【是否分词】是由fieldType的配置决定的,所以不在filed的配置中重复配置。
  30. 2.1.2.dynamicField(动态域)
  31. <dynamicField name="*_s" type="string" indexed="true" stored="true"/>
  32. name:动态域的名称,是一个通配的表达式,*匹配任意字符,只要域的名称和表达式的规则能够匹配就可以使用这个动态域作为普通业务域使用。
  33. 其他属性和正常field域配置一样,没有区别。
  34. 例如:添加索引id=zjl001zhoujielun_s=zhoujielun001,其中zhoujielun_sschema.xml中没有配置,但是这个符合动态域【*_s】,所以仍然可以添加:
  35. @Test
  36. public void testCreateIndex() throws Exception {
  37. // URL
  38. String baseUrl = "http://localhost:8081/solr/collection1";
  39. // 创建HttpSolrServer
  40. HttpSolrServer solrServer = new HttpSolrServer(baseUrl);
  41. // 创建document对象
  42. SolrInputDocument document = new SolrInputDocument();
  43. document.addField("id", "zjl001");
  44. document.addField("zhoujielun_s", "zhoujielun001");
  45. solrServer.add(document);
  46. solrServer.commit();
  47. }
  48.  
  49. 2.1.3.uniqueKey
  50. <uniqueKey>id</uniqueKey>
  51. 声明一个主域,要求所有的Document中都必须包含这里声明的field域,相当于数据库表的主键。声明的域名必须存在。
  52. 2.1.4.copyField(复制域)
  53. <copyField source="cat1" dest="text"/>
  54. <copyField source="cat2" dest="text"/>
  55. 可以将多个field域合并到一个field域中,以便进行统一的检索。
  56. 例如:cat1cat2text是三个普通的field域,在创建索引时,solr会自动将cat1cat2复制到text域中,那么查询text域就相当于查询cat1域和cat2域了。
  57. source:源域
  58. dest:目标域,搜索时,指定目标域为默认搜索域,可以提高查询效率。
  59. 无论是源域还是目标域都得是已经存在的,并且目标域的multiValued必须是true
  60. 定义目标域:
  61. <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
  62.  
  63. 2.1.5.fieldType(域类型)
  64. solr可以根据需要自己配置域的定义,域的定义包括:一个Solr底层的Field域类型和根据需要选定的分析器。
  65. solr这样设计的好处是能获得更好的扩展性,同一种solrField域类型可以根据不同的分析器扩展出多个自定义域类型来,使用起来更加灵活。
  66. <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  67. <analyzer type="index">
  68. <tokenizer class="solr.StandardTokenizerFactory"/>
  69. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  70. <!-- in this example, we will only use synonyms at query time
  71. <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
  72. -->
  73. <filter class="solr.LowerCaseFilterFactory"/>
  74. </analyzer>
  75. <analyzer type="query">
  76. <tokenizer class="solr.StandardTokenizerFactory"/>
  77. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  78. <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
  79. <filter class="solr.LowerCaseFilterFactory"/>
  80. </analyzer>
  81. </fieldType>
  82.  
  83. name:域类型的别名
  84. class:指定solr的域类型。
  85. analyzer:指定分词器。在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词器和过滤器。
  86. 还可以直接指定一个分析器的class类,这样就使用这个分析器中自带的分词器和过滤器,而不需要再在这里配置分词器和过滤器了。这样的配置更加简化。
  87. type:值为indexqueryindex 是创建索引,query是查询索引。
  88. tokenizer:指定分词器
  89. filter:指定过滤器
  90.  
  91. 2.2.配置中文分析器
  92. SolrCore中配置fieldTypeSolr底层域类型都是来自solr服务中的solr jar包的,如果想要引入IK中文分词器需要在solr服务的lib中加入IKjar包。
  93. 第一步:添加IKAnalyzer2012FF_u1.jarsolr/WEB-INF/lib目录下。
  94.  
  95. 第二步:配置IK分析器
  96. solr/WEB-INF/下创建classes文件夹,添加IK的配置文件、自定义扩展词库、停用词词库。
  97.  
  98. 第三步:配置日志输出
  99.  
  100. 第三步:在schema.xml中添加一个自定义的fieldType,使用中文分析器。
  101. <!-- fileType with IKAnalyzer -->
  102. <fieldType name="text_ik" class="solr.TextField">
  103. <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer" />
  104. </fieldType>
  105.  
  106. 第四步:在schema.xml中添加field,指定fieldtype属性为text_ik
  107. <!-- IKAnalyzer Field -->
  108. <field name="content_ik" type="text_ik" indexed="true" stored="true" />
  109.  
  110. 第五步:重启tomcat
  111. 效果:
  112.  
  113. 3.业务域的配置和批量索引(重点)
  114. 3.1.业务需求
  115. 一个web系统都会有一个站内搜索应用,要开发站内搜索第一个问题就是如何将数据库的数据批量导入索引库?数据导入索引库的确认事项:
  116. 1. 需要需要的表字段和检索数据
  117. 2. 根据表字段在schema.xml中配置业务域
  118. 3. schema.xml中配置一个导入数据的requestHandler
  119. 3.2.数据库表字段和数据
  120. 3.2.1.导入数据SQL脚本
  121. 在数据库中运行solr.sql脚本
  122.  
  123. 导入数据:总共3803条数据
  124.  
  125. 3.2.2.查询SQL
  126. SELECT pid,name,catalog_name,price,description,picture FROM products
  127. 3.3.配置业务Field
  128. 先确定定义的商品documentField域有哪些?
  129. 可以根据我们要查询的有哪些商品表的字段来确定:
  130. products商品表:
  131.  
  132. SolrCoreschema.xml中配置业务域,就根据我们检索的字段来创建:
  133. <!-- products Field -->
  134. <field name="product_name" type="text_ik" indexed="true" stored="true" />
  135. <field name="product_catalog_name" type="string" indexed="true" stored="true" />
  136. <field name="product_price" type="float" indexed="true" stored="true" />
  137. <field name="product_description" type="text_ik" indexed="true" stored="false" />
  138. <field name="product_picture" type="string" indexed="false" stored="true" />
  139. <!-- products copyField -->
  140. <field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
  141. <copyField source="product_name" dest="product_keywords"/>
  142. <copyField source="product_description" dest="product_keywords"/>
  143. 注意:这里没有创建idfield,因为在schema.xml中默认自带idfield,而且必须包含这个id域,所以这里不用建。
  144.  
  145. 3.4.配置数据导入requestHandler
  146. 在昨天也介绍solr的可视化管理工具中有一个Dataimport功能,就是用于批量导入数据创建索引的:
  147.  
  148. 在上一节我们已经事先配置了业务域,下面需要利用批量导入插件将mysql中的products表中的数据批量创建索引:
  149. 3.4.1.第一步:导入插件依赖jar
  150. 先在一个SolrCore实例(collection1)下创建一个lib文件夹,然后把dataimport插件依赖的jar包添加到lib中, 同时还需要mysql的数据库驱动。
  151.  
  152. 3.4.2.第二步:配置solrconfig.xml
  153. 配置solrconfig.xml文件,添加一个requestHandler
  154. <!-- A request handler that dataimport -->
  155. <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
  156. <lst name="defaults">
  157. <str name="config">data-config.xml</str>
  158. </lst>
  159. </requestHandler>
  160.  
  161. 创建一个data-config.xml,与solrconfig.xml保存到同目录下
  162. <?xml version="1.0" encoding="UTF-8" ?>
  163. <dataConfig>
  164. <dataSource type="JdbcDataSource"
  165. driver="com.mysql.jdbc.Driver"
  166. url="jdbc:mysql://localhost:3306/lucene"
  167. user="root"
  168. password="123"/>
  169. <document>
  170. <entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products">
  171. <field column="pid" name="id"/>
  172. <field column="name" name="product_name"/>
  173. <field column="catalog_name" name="product_catalog_name"/>
  174. <field column="price" name="product_price"/>
  175. <field column="description" name="product_description"/>
  176. <field column="picture" name="product_picture"/>
  177. </entity>
  178. </document>
  179. </dataConfig>
  180.  
  181. 3.4.3.第三步:重启tomcat
  182. 重启tomcat,然后刷新页面,点击Dataimport就可以看到这个导入界面了:
  183.  
  184. 点击“execute”按钮导入数据。
  185. 界面重要选项说明:
  186. ·Command
  187. full-import表示全部导入
  188. delta-import表示差分导入(把缺少的部分导入进来)
  189. 一般我们为了导入的数据完整,都采用full-import
  190. ·Clean:(默认选中)表示导入数据前会自动清空之前的索引文件
  191. ·Commit:(默认选中)表示创建的索引会自动提交
  192. ·Auto-Refresh Status:(默认不选中)它是控制到导入数据过程中界面是否自动刷新,默认不自动,要想自动选中即可。
  193. 导入成功界面:
  194.  
  195. 3.5.测试导入的索引
  196. 3.5.1.solr的查询语法
  197. 1.q:查询关键字,必须的。
  198. 请求的q是字符串,如果查询所有使用*:*
  199.  
  200. 2.fq: (filter query)过滤查询
  201. 作用:在q查询符合结果中同时是fq查询符合的
  202. 请求fq是一个数组(多个值)
  203.  
  204. 过滤查询价格从120的记录。
  205.  
  206. 也可以使用“*”表示无限,例如:
  207. 20以上:product_price:[20 TO *]
  208. 20以下:product_price:[* TO 20]
  209.  
  210. 也可以在“q”查询条件中使用product_price:[1 TO 20],
  211. 如下效果和上面一样:
  212.  
  213. 3.sort: 排序,desc代表降序,asc代表升序
  214. 按照价格升序排
  215.  
  216. 4.start: 分页显示使用,开始记录下标,从0开始
  217. rows: 指定返回结果最多有多少条记录,配合start来实现分页。
  218.  
  219. 5.fl: (Field List)指定返回那些字段内容,用逗号或空格分隔多个。
  220.  
  221. 显示商品id、商品名称、商品分类名称
  222.  
  223. 6.df: 指定默认搜索Field
  224.  
  225. 7.wt: (writer type)指定输出格式,可以有 xml, json, php, python
  226.  
  227. 8.hl: 是否高亮 ,设置高亮Field,设置格式前缀和后缀。
  228.  
  229. 3.5.2.solrj的复杂查询
  230. 页面的查询条件,复杂查询条件和页面的查询条件一致
  231.  
  232. 上面的查询条件也可以用代码实现:
  233. /**
  234. * solrj复杂查询
  235. *
  236. * @throws Exception
  237. */
  238. @Test
  239. public void complexSearchIndexTest() throws Exception {
  240. // 查询条件设置
  241. SolrQuery solrQuery = setQueryConditions();
  242. // 执行查询
  243. QueryResponse response = solrServer.query(solrQuery);
  244. // 处理查询查询结果
  245. dealSearchResult(response);
  246. }
  247.  
  248. // 查询条件设置
  249. private SolrQuery setQueryConditions() throws Exception {
  250. SolrQuery query = new SolrQuery();
  251. // 设置查询条件
  252. query.setQuery("台灯");
  253.  
  254. // 设置过滤条件
  255. query.setFilterQueries("product_catalog_name:雅致灯饰", "product_price:[30 TO 40]");
  256. // 或者分开设置
  257. /*query.setFilterQueries("product_catalog_name:雅致灯饰");
  258. query.setFilterQueries("product_price:[30 TO 40]");*/
  259.  
  260. // 设置排序条件
  261. query.setSort("product_price", ORDER.desc);
  262.  
  263. // 设置分页信息(开始行号和每页数据量)
  264. query.setStart(0);
  265. query.setRows(10);
  266.  
  267. // 设置需要显示的域名(可选,不设置时全部显示)
  268. //query.setFields("id", "product_name", "product_price");
  269.  
  270. // 设置默认搜索域
  271. query.set("df", "product_name");
  272.  
  273. // 设置高亮显示(是否开启高亮显示,高亮显示的域名,高亮的前缀和后缀)
  274. query.setHighlight(true);
  275. query.addHighlightField("product_name");
  276. query.setHighlightSimplePre("<font color=\"red\">");
  277. query.setHighlightSimplePost("</font>");
  278.  
  279. return query;
  280. }
  281.  
  282. // 处理查询结果
  283. private void dealSearchResult(QueryResponse response) throws Exception {
  284. // 取得商品信息结果集
  285. SolrDocumentList results = response.getResults();
  286.  
  287. // 取得高亮信息结果集
  288. Map<String, Map<String, List<String>>> hlResults = response.getHighlighting();
  289.  
  290. // 打印结果件数
  291. System.out.println("查询结果总件数:" + results.getNumFound());
  292.  
  293. // 遍历结果集打印结果
  294. for (SolrDocument doc : results) {
  295. System.out.println("-=-=-=-=-=-=-=-=-=");
  296. // 处理高亮显示的内容
  297. String hlValue = dealHighlighting(hlResults, doc, "product_name");
  298.  
  299. // 输出结果
  300. System.out.println("id:" + doc.get("id"));
  301. System.out.println("product_name:" + hlValue);
  302. System.out.println("product_price:" + doc.get("product_price"));
  303. System.out.println("product_catalog_name:" + doc.get("product_catalog_name"));
  304. System.out.println("product_picture:" + doc.get("product_picture"));
  305. }
  306. }
  307.  
  308. // 处理高亮显示内容
  309. private String dealHighlighting(Map<String, Map<String, List<String>>> hlResults,
  310. SolrDocument doc, String hlField) throws Exception {
  311. // 先取得原版的域值
  312. String orgFieldValue = (String)doc.get(hlField);
  313.  
  314. // 判断高亮结果集中是否包含当前文档的高亮信息
  315. if (hlResults != null) {
  316. List<String> list = hlResults.get(doc.get("id")).get(hlField);
  317. if (list != null && list.size() > 0) {
  318. return list.get(0);
  319. }
  320. }
  321. return orgFieldValue;
  322. }
  323.  
  324. 4.案例(重点)
  325. 4.1.需求
  326. 使用Solr实现电商网站中商品信息搜索功能,可以根据关键字搜索商品信息,根据商品分类、价格过滤搜索结果,也可以根据价格进行排序,实现分页。
  327. 界面如下:
  328.  
  329. 4.1.1.架构分析
  330.  
  331. 架构分为:
  332. 1solr服务器
  333. 2、自己的web服务器(需要开发)
  334. 3、数据库mysql
  335.  
  336. 自己开发的应用
  337. 1Controller
  338. 获取搜索条件,调用查询站内搜索service进行查询,并响应搜索结果到前台页面。
  339. 2Service
  340. Service调用dao, 用前台传入的查询条件创建SolrQuery对象,然后传给DAO,进行搜索。
  341. Service调用dao进行商品数据的维护时,要同步更新索引库(本案例不实现)
  342. 3Dao
  343. 根据service传入的SolrQuery对象,对solr的索引库进行搜索,并返回查询结果。
  344. 对商品数据进行维护和查询(本案例不实现)
  345. 4.2.环境准备
  346. Solr4.10.3
  347. Jdk环境:1.7
  348. IDE环境:eclipse Mars2
  349. 服务器:Tomcat 7
  350. 4.3.工程搭建(UTF-8
  351. 创建一个web工程导入jar
  352. 1spring的相关jar
  353. 2solrJjar包和依赖jar
  354. 3Solr服务的日志依赖包,\solr\example\lib\ext下的jar
  355. 创建后完整的工程:
  356.  
  357. 1. 导入jar包后,先创建目录:daopojoservicecontrollerconfigjsp
  358. 2. 导入配置文件:
  359. 1) 表现层SpringMVC.xml@controller注解扫描,注解驱动,视图解析器
  360. 2) 业务层ApplicationContext.xml@Service@Repository注解扫描、solrj连接Solr服务的bean
  361. (注意:这里面没有集成mybatis,所以我们用注解@Repository来注入,这样DAO需要有实现类我们自己编写。)
  362. 3) web.xmlSpringMVC的前端控制器和Spring监听
  363. 4) log4j.properties
  364. 3. 导入jsp页面:【资料\jd案例\product_list.jsp
  365. 4. 导入静态资源:【资料\jd案例\】下的【images】【resource】拷贝到工程【WebContent】下。
  366. 5. 导入pojo:【资料\jd案例\pojo\】下的【ProductModel.java】【ResultModel.java
  367. 6. ApplicationContext.xml中配置SolrServer:
  368. <!-- 配置solr server bean -->
  369. <bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
  370. <!-- 配置Solr Server实例时需要的构造函数的参数 -->
  371. <constructor-arg value="http://127.0.0.1:8081/solr/collection1" />
  372. </bean>
  373.  
  374. 4.4.Dao
  375. 功能:接收service层传递过来的参数,根据参数查询索引库,返回查询结果。
  376. 参数:SolrQuery对象
  377. 返回值:一个商品列表List<ProductModel>,还需要返回查询结果的总数量。
  378. 返回:ResultModel
  379. 方法定义:ResultModel searchProductList(SolrQuery query) throws Exception;
  380.  
  381. 商品对象模型:
  382. public class ProductModel {
  383. // 商品编号
  384. private String pid;
  385. // 商品名称
  386. private String name;
  387. // 商品分类名称
  388. private String catalog_name;
  389. // 价格
  390. private float price;
  391. // 商品描述
  392. private String description;
  393. // 图片名称
  394. private String picture;
  395. }
  396.  
  397. 返回值对象模型
  398. public class ResultModel {
  399. // 商品列表
  400. private List<ProductModel> productList;
  401. // 商品总数
  402. private Long recordCount;
  403. // 总页数
  404. private int pageCount;
  405. // 当前页
  406. private int curPage;
  407. }
  408.  
  409. package cn.baidu.dao;
  410. import java.util.ArrayList;
  411. import java.util.List;
  412. import java.util.Map;
  413. import org.apache.solr.client.solrj.SolrQuery;
  414. import org.apache.solr.client.solrj.SolrServer;
  415. import org.apache.solr.client.solrj.response.QueryResponse;
  416. import org.apache.solr.common.SolrDocument;
  417. import org.apache.solr.common.SolrDocumentList;
  418. import org.springframework.beans.factory.annotation.Autowired;
  419. import org.springframework.stereotype.Repository;
  420. import cn.baidu.pojo.ProductModel;
  421. import cn.baidu.pojo.ResultModel;
  422.  
  423. @Repository
  424. public class ProductDaoImpl implements ProductDao {
  425. @Autowired
  426. private SolrServer solrServer;
  427. @Override
  428. public ResultModel searchProductList(SolrQuery query) throws Exception {
  429. // 执行查询,并返回结果
  430. QueryResponse queryResponse = solrServer.query(query);
  431. // 从结果对象中取得结果集
  432. SolrDocumentList results = queryResponse.getResults();
  433. // 创建返回结果对象
  434. ResultModel resultModel = new ResultModel();
  435. // 创建结果集list
  436. List<ProductModel> productList = new ArrayList<ProductModel>();
  437. // 查询件数
  438. resultModel.setRecordCount(results.getNumFound());
  439. // 遍历结果集打印详细内容
  440. for (SolrDocument doc : results) {
  441. // 创建一个ProductModel查询结果
  442. ProductModel productModel = new ProductModel();
  443.  
  444. // 取得高亮显示的信息,然后根据高亮显示的信息进行结果信息打印
  445. String productName = (String)doc.get("product_name");
  446. Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
  447. if (highlighting != null) {
  448. List<String> list = highlighting.get(doc.get("id")).get("product_name");
  449. if (list != null && list.size() > 0) {
  450. productName = list.get(0);
  451. }
  452. }
  453. // 商品id
  454. productModel.setPid(String.valueOf(doc.get("id")));
  455. // 商品名称
  456. productModel.setName(productName);
  457. // 商品价格
  458. String price = String.valueOf(doc.get("product_price"));
  459. if (price != null && !"".equals(price)) {
  460. productModel.setPrice(Float.parseFloat(price));
  461. }
  462. // 商品图片
  463. productModel.setPicture(String.valueOf(doc.get("product_picture")));
  464. // 添加到商品列表中
  465. productList.add(productModel);
  466. }
  467. if (productList.size() > 0) {
  468. resultModel.setProductList(productList);
  469. }
  470. return resultModel;
  471. }
  472. }
  473.  
  474. 4.5.Service
  475. 功能:接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
  476. 参数:
  477. 1、查询条件:字符串
  478. 2、商品分类的过滤条件:商品的分类名称,字符串
  479. 3、商品价格区间:传递一个字符串,满足格式:“0-100101-200201-*”
  480. 4、排序条件:页面传递过来一个升序或者降序就可以,默认是价格排序。0:升序1:降序
  481. 5、分页信息:每页显示的记录条数创建一个常量60条。传递一个当前页码就可以了。
  482. 返回值:ResultModel
  483.  
  484. 方法定义:ResultModel queryProduct(String queryString, String caltalog_name, String price, String sort, Integer page) throws Exception;
  485. package cn.baidu.service;
  486. import org.apache.solr.client.solrj.SolrQuery;
  487. import org.apache.solr.client.solrj.SolrQuery.ORDER;
  488. import org.springframework.beans.factory.annotation.Autowired;
  489. import org.springframework.stereotype.Service;
  490. import cn.baidu.dao.ProductDao;
  491. import cn.baidu.pojo.ResultModel;
  492. @Service
  493. public class ProductServiceImpl implements ProductService {
  494. // 每页显示60条数据
  495. private static final Integer PAGE_SIZE = 60;
  496. @Autowired
  497. private ProductDao prodDao;
  498. @Override
  499. public ResultModel search(String queryString, String catalog_name,
  500. String price, Integer page, String sort)
  501. throws Exception {
  502. // 封装查询条件
  503. SolrQuery solrQuery = new SolrQuery();
  504. // 设置默认查询域
  505. solrQuery.set("df", "product_keywords");
  506. // 设置查询条件
  507. if (queryString != null && !"".equals(queryString)) {
  508. solrQuery.setQuery(queryString);
  509. } else {
  510. solrQuery.setQuery("*:*");
  511. }
  512. // 根据分类过滤
  513. if (catalog_name != null && !"".equals(catalog_name)) {
  514. solrQuery.addFilterQuery("product_catalog_name:" + catalog_name);
  515. }
  516. // else {
  517. // // 注意这里要说一下为什么没有else,因为过滤条件不是必须的所以可以没有.
  518. // }
  519. // 价格过滤
  520. if (price != null && !"".equals(price)) {
  521. String[] split = price.split("-");
  522. if (split != null && split.length > 0) {
  523. solrQuery.addFilterQuery("product_price:[" + split[0] + " TO " + split[1] + "]");
  524. }
  525. }
  526. // 排序
  527. if ("1".equals(sort)) {
  528. solrQuery.setSort("product_price", ORDER.asc);
  529. } else {
  530. solrQuery.setSort("product_price", ORDER.desc);
  531. }
  532. // 分页
  533. if (page == null || page <= 0) {
  534. page = 1;
  535. }
  536. // 从第几条开始
  537. solrQuery.setStart((page - 1) * PAGE_SIZE);
  538. // 每页显示多少条
  539. solrQuery.setRows(PAGE_SIZE);
  540. // 设置高亮
  541. solrQuery.setHighlight(true);
  542. // 设置高亮显示的域
  543. solrQuery.addHighlightField("product_name");
  544. // 设置高亮前缀
  545. solrQuery.setHighlightSimplePre("<span style=\"color:red\">");
  546. // 设置高亮后缀
  547. solrQuery.setHighlightSimplePost("</span>");
  548. // 根据查询条件取得结果
  549. ResultModel resultModel = prodDao.search(solrQuery);
  550. // 设置当前页
  551. resultModel.setCurPage(page);
  552. // 计算总页数
  553. Long pageCount = resultModel.getRecordCount() / PAGE_SIZE;
  554. if (resultModel.getRecordCount() % PAGE_SIZE > 0) {
  555. pageCount++;
  556. }
  557. resultModel.setPageCount(pageCount);
  558. return resultModel;
  559. }
  560. }
  561.  
  562. 4.1.Controller
  563. 功能:接收页面传递过来的参数调用service查询商品列表。将查询结果返回给jsp页面,还需要查询参数的回显。
  564.  
  565. 参数:
  566. 1、查询条件:字符串
  567. 2、商品分类的过滤条件:商品的分类名称,字符串
  568. 3、商品价格区间:传递一个字符串,满足格式:“0-100101-200201-*”
  569. 4、排序条件:页面传递过来一个升序或者降序就可以,默认是价格排序。0:升序1:降序
  570. 5、分页信息:每页显示的记录条数创建一个常量60条。传递一个当前页码就可以了。
  571. 6Model:相当于request
  572.  
  573. 返回结果:String类型,就是一个jsp的名称。
  574.  
  575. String queryProduct(String queryString, String caltalog_name, String price, String sort, Integer page, Model model) throws Exception;
  576. package cn.baidu.controller;
  577. import org.springframework.beans.factory.annotation.Autowired;
  578. import org.springframework.stereotype.Controller;
  579. import org.springframework.ui.Model;
  580. import org.springframework.web.bind.annotation.RequestMapping;
  581. import cn.baidu.pojo.ResultModel;
  582. import cn.baidu.service.ProductService;
  583. @Controller
  584. public class ProductController {
  585. @Autowired
  586. private ProductService prodService;
  587. @RequestMapping("/list")
  588. public String list(String queryString, String catalog_name,
  589. String price, Integer page, String sort, Model model) throws Exception {
  590. ResultModel resultModel = prodService.search(queryString, catalog_name, price, page, sort);
  591. // 搜索结果返回
  592. model.addAttribute("result", resultModel);
  593. // 回显查询条件
  594. model.addAttribute("queryString", queryString);
  595. model.addAttribute("catalog_name", catalog_name);
  596. model.addAttribute("price", price);
  597. model.addAttribute("sort", sort);
  598. return "product_list";
  599. }
  600. }

Lucene&Solr框架之第三篇的更多相关文章

  1. Lucene&Solr框架之第二篇

    2.1.开发环境准备 2.1.1.数据库jar包 我们这里可以尝试着从数据库中采集数据,因此需要连接数据库,我们一直用MySQL,所以这里需要MySQL的jar包 2.1.2.MyBatis的jar包 ...

  2. Lucene&Solr框架之第一篇

    2.信息检索 信息检索是计算机世界中非常重要的一种功能.信息检索不仅仅是指从数据库检索数据,还包括从文件.网页.邮件.用户手输入的内容中检索数据.通过怎样的高效方式将用户想要的信息快速提取出来,是计算 ...

  3. MyBatis框架之第三篇

    8.Spring与Mybatis整合 框架的整合就是软件之间的集成,它很抽象,因此在做整合之前先想好思路.规划好思路然后按照思路一步一步的做就可以实现框架的整合. 8.1.SM整合思路 8.1.1.思 ...

  4. Django(四)框架之第三篇模板语法

    https://www.cnblogs.com/yuanchenqi/articles/6083427.htm https://www.cnblogs.com/haiyan123/p/7725568. ...

  5. Django框架之第三篇模板语法(重要!!!)

    一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 一.模板语法之变量:语法为 {{ }}: 在 Django 模板中遍历复杂数据结构的关键 ...

  6. Django框架之第三篇模板语法

    一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 一.模板语法之变量:语法为 {{ }}: 在 Django 模板中遍历复杂数据结构的关键 ...

  7. SpringMVC框架之第三篇

    2.高级参数绑定(重点) 2.1.数组类型 数组类型的参数可以传递一批相同的数据到Controller的方法中. 2.1.1.需求 批量删除:在商品列表页面选中多个商品,然后删除. 2.1.2.需求分 ...

  8. Django框架之第三篇(路由层)--有名/无名分组、反向解析、路由分发、名称空间、伪静态

    一.Django请求生命周期 二.路由层  urls.py url()方法 第一个参数其实就是一个正则表达式,一旦前面的正则匹配到了内容,就不会再往下继续匹配,而是直接执行对应的视图函数. djang ...

  9. 开源DDD设计模式框架YMNNetCoreFrameWork第三篇-增加ASp.net core Identity身份认证,JWT身份认证

    1.框架增加Identity注册功能 2.框架增加identity登录以后获取JWTtoken 3.请求接口通过token请求,增加验证特性 源代码地址:https://github.com/topg ...

随机推荐

  1. 数据库Oracle的子查询练习

    1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 last name和 hire date,结果中不包括 Zlotkey --1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 ...

  2. ARTS-S k8s配制文件demo

    apiVersion: extensions/v1beta1 kind: Deployment metadata: name: go-demo-hostname spec: replicas: 2 t ...

  3. 小白进阶之路—python脚本(1)判断是否是一个目录

    #!/usr/bin/env python# -*- coding: utf-8 -*-import os   dir = "/var/www/html/EnjoyWeekend/" ...

  4. JavaScript 逻辑与(&&) 与 逻辑或(||) 运算规则

    逻辑与(&&) 逻辑与(&&)操作可以应用于任何的操作类型,不仅仅是布尔值, 在有一个操作数不是布尔值的情况下,&&操作符就不一定返回布尔值:遵循下面规 ...

  5. 4种MySQL分页查询优化的方法,你知道几个?

    前言 当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点.下面简单说一下我知道的 ...

  6. 如何用Postman做接口测试

    postman介绍&测试准备: postman介绍:postman是一个开源的接口测试工具,无论是做单个接口的测试还是整套测试脚本的拨测都非常方便. 前期准备:测试前,需要安装好postman ...

  7. Atmel Studio 7.0 的使用方法

    就在最近,Atmel终于推出了新版本IDE——Atmel Studio 7.0,该版本采用了微软最新的 Visual Studio 2015 平台,经过一段时间使用,Atmel Studio 7.0在 ...

  8. 将数据库中数据导出为excel表格

    public class Excel { private static Logger logger = LoggerFactory.getLogger(Excel.class); /** * 导出项目 ...

  9. Codeforces Round #599 (Div. 2)

    久违的写篇博客吧 A. Maximum Square 题目链接:https://codeforces.com/contest/1243/problem/A 题意: 给定n个栅栏,对这n个栅栏进行任意排 ...

  10. 大白话简单工厂模式 (Simple Factory Pattern)

    大白话简单工厂模式 (Simple Factory Pattern) 从买车经历说起 毕业两年,码农张小两口无法忍受挤公交,凌晨起床抢火车票的痛苦,遂计划买车.逛了多家4S店,最终定下日产某车型的轿车 ...