现在移动开发中越来越多的App都有周边搜索,有找附近的人的,附近的酒店,附近的餐馆的。接下来我们就来讲一下强大的Solr来帮我们构建周边搜索之酒店搜索。
1 下载 Solr 3.6.2
下载地址:http://www.apache.org/dyn/closer.cgi/lucene/solr/3.6.2
提取apache-solr-3.6.2.zip里的apache-solr-3.6.2.war到F:\, 后面会讲解如何部署这个war包
2 建立solr的索引库配置
2.1 在D:\建立目录hotel_solr
2.2 在D:\hotel_solr下新建solr.xml,内容如下:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <solrpersistent="false">
- <coresadminPath="/admin/cores">
- <corename="core0"instanceDir="core0"/>
- <!--<core name="core1" instanceDir="core1" />-->
- </cores>
- </solr>
2.4 在D:\hotel_solr\core0\conf目录下,新建schema.xml文件,内容如下:
- <?xmlversion="1.0"?>
- <schemaname="example core zero"version="1.1">
- <types>
- <fieldTypename="string"class="solr.StrField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="boolean"class="solr.BoolField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="integer"class="solr.IntField"omitNorms="true"/>
- <fieldTypename="int"class="solr.TrieIntField"precisionStep="0"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="float"class="solr.TrieFloatField"precisionStep="0"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="long"class="solr.TrieLongField"precisionStep="0"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="double"class="solr.TrieDoubleField"precisionStep="0"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="tint"class="solr.TrieIntField"precisionStep="8"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="tfloat"class="solr.TrieFloatField"precisionStep="8"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="tlong"class="solr.TrieLongField"precisionStep="8"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="tdouble"class="solr.TrieDoubleField"precisionStep="8"omitNorms="true"positionIncrementGap="0"/>
- <fieldTypename="sint"class="solr.SortableIntField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="slong"class="solr.SortableLongField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="sfloat"class="solr.SortableFloatField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="sdouble"class="solr.SortableDoubleField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="date"class="solr.TrieDateField"omitNorms="true"precisionStep="0"positionIncrementGap="0"/>
- <fieldTypename="tdate"class="solr.TrieDateField"omitNorms="true"precisionStep="6"positionIncrementGap="0"/>
- <fieldtypename="ignored"stored="false"indexed="false"class="solr.StrField"/>
- <fieldtypename="location"class="solr.LatLonType"subFieldSuffix="_d"/>
- <fieldTypename="text"class="solr.TextField"positionIncrementGap="100">
- <analyzertype="index">
- <tokenizerclass="solr.StandardTokenizerFactory"/>
- <filterclass="solr.LowerCaseFilterFactory"/>
- </analyzer>
- <analyzertype="query">
- <tokenizerclass="solr.StandardTokenizerFactory"/>
- <filterclass="solr.LowerCaseFilterFactory"/>
- </analyzer>
- </fieldType>
- </types>
- <fields>
- <fieldname="hotel_id"type="integer"indexed="true"stored="true"required="true"/>
- <fieldname="crawl_hotel_id" type="string" indexed="true" stored="true" multiValued="false"required="true"/>
- <fieldname="name" type="text" indexed="true" stored="true" multiValued="false"required="true"/>
- <fieldname="address" type="text" indexed="true" stored="true" multiValued="false"required="true"/>
- <fieldname="search_kw"type="text"indexed="true"multiValued="true"stored="false"/>
- <fieldname="latlng"type="location"indexed="true"/>
- <dynamicFieldname="*_d"type="double"indexed="true"stored="true"/>
- </fields>
- <copyFieldsource="name"dest="search_kw"/>
- <copyFieldsource="address"dest="search_kw"/>
- <uniqueKey>hotel_id</uniqueKey>
- <defaultSearchField>search_kw</defaultSearchField>
- <solrQueryParserdefaultOperator="AND"/>
- </schema>
- <?xmlversion="1.0"encoding="UTF-8"?>
- <config>
- <luceneMatchVersion>LUCENE_36</luceneMatchVersion>
- <directoryFactoryname="DirectoryFactory"class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
- <updateHandlerclass="solr.DirectUpdateHandler2"/>
- <requestDispatcherhandleSelect="true">
- <requestParsersenableRemoteStreaming="false"multipartUploadLimitInKB="2048"/>
- </requestDispatcher>
- <requestHandlername="standard"class="solr.StandardRequestHandler"default="true"/>
- <requestHandlername="/update"class="solr.XmlUpdateRequestHandler"/>
- <requestHandlername="/admin/"class="org.apache.solr.handler.admin.AdminHandlers"/>
- <admin>
- <defaultQuery>*:*</defaultQuery>
- </admin>
- </config>
3 配置tomcat
3.1 让tomcat支持HTTP GET UTF-8编码的支持, 打开D:\apache-tomcat-7.0.16\conf\server.xml,修成如下地方:
- <Connectorport="8080"protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443"URIEncoding="UTF-8"/>
在D:\apache-tomcat-7.0.16\conf\Catalina\localhost新建solr.xml,内容如下:
- <ContextdocBase="F:/apache-solr-3.6.2.war"debug="0"crossContext="true">
- <Environmentname="solr/home"type="java.lang.String"value="D:/hotel_solr"override="true"/>
- </Context>
4 准备酒店数据(如果没有自己去建立)
5 把数据库中的酒店数据添加到Solr索引库中
使用Solrj客户端进行索引构建和查询,MAVEN依赖包:
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.solr</groupId>
- <artifactId>solr-solrj</artifactId>
- <version>3.6.0</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.19</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.1.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient-cache</artifactId>
- <version>4.1.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpmime</artifactId>
- <version>4.1.3</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.6.4</version>
- </dependency>
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.HashMap;
- import java.util.Map;
- import org.apache.commons.lang.StringUtils;
- import org.apache.solr.client.solrj.SolrRequest.METHOD;
- import org.apache.solr.client.solrj.impl.HttpSolrServer;
- import org.apache.solr.client.solrj.response.QueryResponse;
- import org.apache.solr.common.SolrDocumentList;
- import org.apache.solr.common.SolrInputDocument;
- import org.apache.solr.common.params.MapSolrParams;
- public class App {
- /**
- * 初始化索引数据
- * @param solrServer
- * @throws Exception
- */
- public staticvoid buildIndex(String solrServer)throws Exception {
- Connection connect = null;
- Statement statement = null;
- ResultSet resultSet = null;
- HttpSolrServer server = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- connect = DriverManager
- .getConnection("jdbc:mysql://localhost/hotel_analysis?"
- + "user=root&password=11111");
- statement = connect.createStatement();
- resultSet = statement
- .executeQuery("select hotel_id,crawl_hotel_id,hotel_name,hotel_address,hotel_location from crawl_hotel");
- server = new HttpSolrServer(solrServer);
- int count = 0;
- int eachCommit = 100;
- //从数据库中获取酒店数据
- while (resultSet.next()) {
- Integer hotel_id = resultSet.getInt(1);
- String crawl_hotel_id = resultSet.getString(2);
- String hotel_name = resultSet.getString(3);
- String hotel_address = resultSet.getString(4);
- String hotel_location = resultSet.getString(5);
- if (StringUtils.isBlank(hotel_location)) {
- continue;
- }
- count++;
- //添加酒店数据到Solr索引中
- SolrInputDocument doc = new SolrInputDocument();
- doc.addField("hotel_id", hotel_id);
- doc.addField("crawl_hotel_id", crawl_hotel_id);
- doc.addField("name", hotel_name);
- doc.addField("address", hotel_address);
- doc.addField("latlng", hotel_location);
- server.add(doc);
- //100条commit一次
- if (count % eachCommit ==0) {
- server.commit();
- count = 0;
- }
- }
- if (count > 0) {
- server.commit();
- count = 0;
- }
- } finally {
- if (null != resultSet) {
- try {
- resultSet.close();
- } catch (SQLException ex) {
- }
- }
- if (null != statement) {
- try {
- statement.close();
- } catch (SQLException ex) {
- }
- }
- if (null != connect) {
- try {
- connect.close();
- } catch (SQLException ex) {
- }
- }
- }
- }
- public staticvoid main(String[] args)throws Exception {
- String URL = "http://localhost:8080/solr/core0";
- //构建索引到Solr库
- buildIndex(URL);
- //索引周边查询
- //queryTest(URL);
- }
- /**
- * 测试索引查询
- * http://localhost:8080/solr/core0/select?q=*%3A*&fq=%7B%21geofilt%7D&pt=31.26552%2C121.460815&sfield=latlng&d=2&sort=geodist%28%29+asc&fl=*%2Cscore&start=0&rows=10
- * @param solrServer
- * @throws Exception
- */
- public staticvoid queryTest(String solrServer)throws Exception {
- HttpSolrServer server = new HttpSolrServer(solrServer);
- Map<String,String> params = new HashMap<String,String>();
- params.put("q", "*:*");
- params.put("fq", "{!geofilt}");//距离过滤函数
- params.put("pt", "31.26552,121.460815");//当前经纬度
- params.put("sfield", "latlng");//经纬度的字段
- params.put("d", "2");//就近2公里的所有酒店
- params.put("sort", "geodist() asc");//根据距离排序
- params.put("fl", "*,score");
- params.put("start", "0");//记录开始位置
- params.put("rows", "10");//查询的行数
- QueryResponse resp = server.query(new MapSolrParams(params), METHOD.POST);
- SolrDocumentList docs = resp.getResults();
- for(int i=0;i<docs.size();i++){
- System.out.println(docs.get(i));
- }
- }
- }
6 查询展示:
查询结果页: