http://xiaofancn.iteye.com/blog/1424252
http://wiki.apache.org/solr/Solrj
http://hi.baidu.com/channing07/blog/item/cb840754a98fc7c9b645ae3e.html
* https://github.com/dsmiley/SOLR-2155 关于位置的搜索的增强库
* http://wiki.apache.org/solr/SpatialSearch#SOLR-2155
为了让paoding适合高版本的solr3.5,我重新更换了一下paoding编译的部分jar包。
jar是从 solr3.5 项目中apache-tomcat-7.0.27\webapps\solr\WEB-INF\lib复制
添加新的分词类
package net.paoding.analysis.analyzer.solr; import java.io.Reader; import java.util.Map; import net.paoding.analysis.analyzer.PaodingTokenizer; import net.paoding.analysis.analyzer.TokenCollector; import net.paoding.analysis.analyzer.impl.MaxWordLengthTokenCollector; import net.paoding.analysis.analyzer.impl.MostWordsTokenCollector; import net.paoding.analysis.knife.PaodingMaker; import org.apache.lucene.analysis.Tokenizer; import org.apache.solr.analysis.BaseTokenizerFactory; public class ChineseTokenizerFactory extends BaseTokenizerFactory { /** * 最多切分 默认模式 */ public static final String MOST_WORDS_MODE = "most-words"; /** * 按最大切分 */ public static final String MAX_WORD_LENGTH_MODE = "max-word-length"; private String mode = null; public void setMode(String mode) { if (mode == null || MOST_WORDS_MODE.equalsIgnoreCase(mode) || "default".equalsIgnoreCase(mode)) { this.mode = MOST_WORDS_MODE; } else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) { this.mode = MAX_WORD_LENGTH_MODE; } else { throw new IllegalArgumentException( "不合法的分析器Mode 参数设置:" + mode); } } @Override public void init(Map<String,String> args) { super.init(args); setMode(args.get("mode")); } public Tokenizer create(Reader input) { return new PaodingTokenizer(input, PaodingMaker.make(), createTokenCollector()); } private TokenCollector createTokenCollector() { if (MOST_WORDS_MODE.equals(mode)) return new MostWordsTokenCollector(); if (MAX_WORD_LENGTH_MODE.equals(mode)) return new MaxWordLengthTokenCollector(); throw new Error("never happened"); } }
编译后,复制paoding-analysis.jar到solr的lib包中
apache-tomcat-7.0.27\webapps\solr\WEB-INF\lib
apache-tomcat-7.0.27\webapps\solr\solr\conf\schema.xml
里面很多field的type是text_general
所以我们修改text_general类型的切词类,
将类型text_general中的
索引和查询的切词类,换成我们的切词类。
<tokenizer class="net.paoding.analysis.analyzer.solr.ChineseTokenizerFactory" mode="most-words"/>
起动tomcat,成功后。
在我们的maven,pom.xml文件中添加solrj
<dependency> <artifactId>solr-solrj</artifactId> <groupId>org.apache.solr</groupId> <version>1.3.0</version> <type>jar</type> <scope>test</scope> </dependency> <dependency> <artifactId>solr-core</artifactId> <groupId>org.apache.solr</groupId> <version>1.3.0</version> <type>jar</type> <scope>test</scope> </dependency>
测试代码,运行前请读下面的注意事项。
package com.snailteam.team.dao; import java.io.IOException; import java.net.MalformedURLException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.XMLResponseParser; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.snailteam.team.model.City; import com.snailteam.team.model.Shop; import com.snailteam.team.service.CityService; import com.snailteam.team.service.ProductService; import com.snailteam.team.service.ShopService; import com.snailteam.team.service.UserService; /** * * https://github.com/dsmiley/SOLR-2155 * http://wiki.apache.org/solr/SpatialSearch#SOLR-2155 * * * @author fansxnet * */ @SuppressWarnings("restriction") @ContextConfiguration(locations = { "classpath*:/META-INF/spring/applicationContext*.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class UserServiceTest { public static String url = "http://localhost:8080/solr/"; public static CommonsHttpSolrServer server; @Before public void before() throws MalformedURLException { server = new CommonsHttpSolrServer(url); server.setParser(new XMLResponseParser()); } @Resource public UserService userService; @PersistenceContext EntityManager em; @Resource ShopService shopService; @Resource CityService cityService; @Resource ProductService productService; @Resource MongoTemplate mongoTemplate; @Test public void testTorecallAdIdList() { } @Test public void testSoleAdd() throws SolrServerException, IOException { City city = cityService.getAll().get(0); List<Shop> shops = shopService.getShops(city); Collection<SolrInputDocument> docs = new HashSet<SolrInputDocument>(); for (Shop shop : shops) { SolrInputDocument doc = new SolrInputDocument(); doc.addField("id", shop.getId()); if (shop.getLatitude() != null && shop.getLongitude() != null) { // latitudes are range -90 to 90 // longitude are range -180 to 180 // doc.addField("loc", // shop.getLongitude() + "," + shop.getLatitude()); doc.addField("shopname", shop.getName()); doc.addField("addr", shop.getAddr()); doc.addField("tel", shop.getTel()); doc.addField("traff", shop.getTraff()); doc.addField("shoploc", shop.getLatitude() + "," + shop.getLongitude()); } docs.add(doc); } server.add(docs); server.commit(); } /** * 暂时不可用 * * @throws SolrServerException * @throws IOException */ @Test public void testSoleSearch() throws SolrServerException, IOException { // // // select?wt=json&indent=true&fl=shopname,addr,tel,traff,shoploc,_dist_:geodist()&q=*:*&sfield=store&pt=39.904392,116.265033&sort=geodist()%20asc SolrQuery query = new SolrQuery(); query.setQuery("shopname:北京");// &q=*:* query.setFacet(true); query.setFacetMinCount(1); query.setFacetLimit(8); // 参数说明 // indent – 返回的结果是否缩进,默认关闭, // fl – 返回的字段 // sfield – spatial point data is "sfield". See the console output // below. // pt – latitude longitude // sort 排序字段 geodist()%20asc 有问题 // ,_dist_:geodist()获取距离不正确,无值 query.set("sfield", "store");// query.set("pt", "39.904392,116.265033"); query.set("sort", "geodist() asc"); query.set("fl", "_dist_:geodist()"); query.setFields("shopname", "addr", "tel", "traff", "shoploc"); server.setParser(new XMLResponseParser());// 设置solrj的解析格式 QueryResponse rsp = server.query(query, METHOD.POST); SolrDocumentList docs = rsp.getResults(); Iterator<SolrDocument> iterator = docs.iterator(); while (iterator.hasNext()) { SolrDocument solrDoc = iterator.next(); System.out.println(solrDoc.getFieldValue("shopname") + "-" + solrDoc.getFieldValue("addr") + "-" + solrDoc.getFieldValue("shoploc") + "-"); } } }
注意:
为了更形象,我们在solr中定义与我们项目一致的feild字段。新加
<!--shop field--> <field name="shopid" type="text_general" indexed="true" stored="true"/> <field name="shopname" type="text_general" indexed="true" stored="true"/> <field name="addr" type="text_general" indexed="true" stored="true"/> <field name="tel" type="text_general" indexed="true" stored="true"/> <field name="traff" type="text_general" indexed="true" stored="true"/> <field name="shoploc" type="location" indexed="true" stored="true" />
打开solr后台管理页面 http://localhost:8080/solr/admin/
search
shopid:3153