solr的几种应用模式

 java, lucence  solr的几种应用模式已关闭评论
11月 162016
 

写的简单明了:

简单介绍一下solr的几种应用模式:

1.single server


这也就是最简单的部署方式了,如果查询量不大,比如就只是一个小公司内部的文档检索系统就可以简单的以singleserver的方式即可。single server的好处是使用简单,但是使用这种方式可用性很难得到保障。

2.replication

如果查询压力很大,singleserver的方式响应不及时,最简单的处理方式就是增加replication。每个replication都可以对外提供服务,这样整体的响应能力就上去了。增加的replication应当添加到新的机器上,这样查询压力才能均衡。replication增加了查询的高性能之外,整个solr服务的可用性也提升了。

3.distributed

上面说了replication就是增加服务到不同的机器上,那么distributed又是怎么回事?实际上distributed使用了solr的分片技术(shard),和replication一样,每个分片节点都可以对外提供服务,但是最重要不同是replication每个副本节点的内容都是一样的,而分片节点之间的内容则是完全不同的。shard1+shard2的内容才构成完整的collection的索引内容。
当有非常多的文档需要索引,一台机器的存储或内存都存在制约的时候就需要考虑使用分片技术。

4.distributed+replication

如果要索引的文档内容巨大,查询请求量也很大就可以结合2、3两种技术。实际上真实生产环境很多都是这样用(通过solrcloud可以方便的应用这种部署模式),如果单纯的分片而不采用副本技术,一旦某个分片坏掉了,整个服务就宕掉了,这样显然是不可靠的,通过建立分片的副本服务可以增加分片节点的可用性。


来自:http://blog.csdn.net/java_zys/article/details/52371932

lucence入门

 lucence  lucence入门已关闭评论
8月 072015
 

一篇很好的lucence入门他文章,推荐下,转自:http://blog.csdn.net/chenghui0317/article/details/10052103

一、Lucene的介绍

     Lucene是一个全文检索的框架,apache组织提供了一个用java实现的全文搜索引擎的开源项目,其功能非常的强大,api非常简单,并且有了全文检索的功能支持可以非常方便的实现根据关键字来搜索整个应用系统的内容,大大提高了用户的体验效果。   使用Lucene来建立、搜索功能和操作数据库有一点像,这样就可想而知,Lucene使用起来还是蛮方便的。

    那么为什么要使用Lucene 呢? 因为如果没有使用Lucene ,那么就要根据某个关键字来搜索数据库表记录, 就要使用like 一个字符一个字符去匹配,这样子查询的方式的要累坏程序员不说,并且查询数据库的性能开销可想而知。

二、Lucene的执行流程

    前面说了Lucene的操作方式和操作数据库有点相似,所以如果要使用Lucene 就要先创建“数据库”,然后往这个“数据表”中一行一行的插入数据,数据插入成功之后,就可以操作这张“数据表”,实现增删改查操作了。

   总的来说,可以这样理解:

  1、创建一个索引文件目录,然后把需要检索的信息 用Field 对应匹配的 封装成一个Document文档对象,将这个对象放入索引文件目录中,这里既可以将索引存放到磁盘中,也可以放入内存中,如果放入内存,那么程序关闭索引就没有了,所以一般都是将索引放入磁盘中;

  2、如果发现信息有问题需要删除,那么索引文件也要删除,否则检索的时候还是会查询得到,这个时候需要根据索引id去删除对应的索引;

  3、如果发现信息被更新了,那么索引文件也要更新,这个时候需要先将旧的索引删除然后添加新的索引;

  4、最后重头戏是全文搜索了,这和查询数据库一样,先需要创建索引读取对象,然后封装Query查询对象,调用search()方法 得到检索结果。

三、使用Lucene的准备条件

   lucene-core-3.6.0.jar

   lucene-highlighter-3.6.0.jar

   lucene-memory-3.6.0.jar

下载地址:http://download.csdn.net/detail/ch656409110/5971413


四、使用Lucene实战

1、使用Lucene将索引 写入内存

实现的思路如下:

   <1>创建了内存目录对象RAMDirectory 和 索引写入器IndexWriter  ;

   <2>利用索引写入器将指定的数据存入内存目录对象中;

   <3>创建IndexSearch 索引查询对象,然后根据关键字封装Query查询对象;

   <4>调用search()方法,将查询的结果返回给TopDocs ,迭代里面所有的Document对象,显示查询结果;

   <5>关闭IndexWriter 写入器,关闭RAMDirectory目录对象。

具体代码如下:

  1. package com.lucene.test;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.analysis.SimpleAnalyzer;  
  6. import org.apache.lucene.document.Document;  
  7. import org.apache.lucene.document.Field;  
  8. import org.apache.lucene.index.IndexWriter;  
  9. import org.apache.lucene.index.Term;  
  10. import org.apache.lucene.search.IndexSearcher;  
  11. import org.apache.lucene.search.Query;  
  12. import org.apache.lucene.search.TermQuery;  
  13. import org.apache.lucene.search.TopDocs;  
  14. import org.apache.lucene.store.RAMDirectory;  
  15.   
  16. /** 
  17.  * lucene 检索内存索引 非常简单的例子 
  18.  *  
  19.  * @author Administrator 
  20.  *  
  21.  */  
  22. public class RAMDirectoryDemo {  
  23.     public static void main(String[] args) throws IOException {  
  24.         long startTime = System.currentTimeMillis();  
  25.         System.out.println(“*****************检索开始**********************”);  
  26.         // 创建一个内存目录对象,所以这里生成的索引不会放在磁盘中,而是在内存中。  
  27.         RAMDirectory directory = new RAMDirectory();  
  28.         /* 
  29.          * 创建索引写入对象,该对象既可以把索引写入到磁盘中也可以写入到内存中。 参数说明:  
  30.          * public IndexWriter(Directory d, Analyzer a, boolean create, MaxFieldLength mfl) 
  31.          * directory:目录对象,也可以是FSDirectory 磁盘目录对象  
  32.          * analyzer:分词器,分词器就是将检索的关键字分割成一组组词组, 它是lucene检索查询的一大特色之一, new SimpleAnalyzer()这个是lucene自带的最为简单的分词器; create: 是否新建,这里肯定要设为true; 
  33.          * maxFieldLength:这个是分词器拆分最大长度,因为各种不同类型的分词器拆分的字符颗粒细化程度不一样,所以需要设置一个最长的拆分长度。IndexWriter.MaxFieldLength.UNLIMITED表示无限制; 
  34.          */  
  35.         IndexWriter writer = new IndexWriter(directory, new SimpleAnalyzer(),true, IndexWriter.MaxFieldLength.UNLIMITED);  
  36.         // 创建Document 文档对象,在lucene中创建的索引可以看成数据库中的一张表,表中也可以有字段,往里面添加内容之后可以根据字段去匹配查询  
  37.         // 下面创建的doc对象中添加了三个字段,分别为name,sex,dosomething,  
  38.         Document doc = new Document();  
  39.         /* 
  40.         * 参数说明 public Field(String name, String value, Store store, Index index)  
  41.         * name : 字段名称  
  42.         * value : 字段的值 store : 
  43.         *  Field.Store.YES:存储字段值(未分词前的字段值) Field.Store.NO:不存储,存储与索引没有关系 
  44.         *  Field.Store.COMPRESS:压缩存储,用于长文本或二进制,但性能受损  
  45.         * index : 建立索引的方式,是否建立分词等等 
  46.         *  Field.Index.ANALYZED:分词建索引 
  47.         *  Field.Index.ANALYZED_NO_NORMS:分词建索引,但是Field的值不像通常那样被保存,而是只取一个byte,这样节约存储空间  
  48.         *  Field.Index.NOT_ANALYZED:不分词且索引 ,一旦指定为这种类型后将会被lucenn录入索引中,但不会被作为关键搜索,除非输入所有的关键字 
  49.         *  Field.Index.NOT_ANALYZED_NO_NORMS:不分词建索引,Field的值去一个byte保存 
  50.         */  
  51.         doc.add(new Field(“name”“Chenghui”, Field.Store.YES,Field.Index.ANALYZED));  
  52.         doc.add(new Field(“sex”“男的”, Field.Store.YES,Field.Index.NOT_ANALYZED));  
  53.         doc.add(new Field(“dosometing”“I am learning lucene “,Field.Store.YES, Field.Index.ANALYZED));  
  54.         writer.addDocument(doc);  
  55.         writer.close(); // 这里可以提前关闭,因为dictory 写入内存之后 与IndexWriter 没有任何关系了  
  56.   
  57.         // 因为索引放在内存中,所以存放进去之后要立马测试,否则,关闭应用程序之后就检索不到了  
  58.         // 创建IndexSearcher 检索索引的对象,里面要传递上面写入的内存目录对象directory  
  59.         IndexSearcher searcher = new IndexSearcher(directory);  
  60.         // 根据搜索关键字 封装一个term组合对象,然后封装成Query查询对象  
  61.         // dosometing是上面定义的字段,lucene是检索的关键字  
  62.          Query query = new TermQuery(new Term(“dosometing”“lucene”));  
  63.         // Query query = new TermQuery(new Term(“sex”, “男”));  
  64.         // Query query = new TermQuery(new Term(“name”, “cheng”));   
  65.           
  66.         // 去索引目录中查询,返回的是TopDocs对象,里面存放的就是上面放的document文档对象  
  67.         TopDocs rs = searcher.search(query, null10);  
  68.         long endTime = System.currentTimeMillis();  
  69.         System.out.println(“总共花费” + (endTime – startTime) + “毫秒,检索到” + rs.totalHits + “条记录。”);  
  70.         for (int i = 0; i < rs.scoreDocs.length; i++) {  
  71.             // rs.scoreDocs[i].doc 是获取索引中的标志位id, 从0开始记录  
  72.             Document firstHit = searcher.doc(rs.scoreDocs[i].doc);  
  73.             System.out.println(“name:” + firstHit.getField(“name”).stringValue());  
  74.             System.out.println(“sex:” + firstHit.getField(“sex”).stringValue());  
  75.             System.out.println(“dosomething:” + firstHit.getField(“dosometing”).stringValue());  
  76.         }  
  77.         writer.close();  
  78.         directory.close();  
  79.         System.out.println(“*****************检索结束**********************”);  
  80.     }  
  81. }  

运行结果如下:

由上可知: 上面根据“lucene”关键字查询成功了,返回的是一个个Document封装的对象。

另外 如果在创建索引写入器IndexWriter的时候 create 参数指定为false的话 ,会报错,找不到索引文件,因为每一次读取都是”现存现取“的模式,具体如下:

Exception in thread “main” org.apache.lucene.index.IndexNotFoundException: no segments* file found in [email protected] [email protected]b480: files: []

根据dosomething可以查询成功,同样根据sex字段 和name字段一样可以实现查询功能。

<1>如果把 Query query = new TermQuery(new Term(“sex”, “男”)); 取消注释 ,然后查询一下:

结果发现根本没有记录,这是因为在生成索引的时候指定的sex字段 是Field.Index.NOT_ANALYZED 类型的,所以Lucene没有为该字段建立索引,也就不能根据sex字段去查询。

<2>然后 将sex 字段改为Field.Index.ANALYZED类型的,再查询一下:

结果发现依然没有记录,为什么?

这是因为使用的分词器SimpleAnalyzer 没有那么智能化,它只会对关键字中包含空格的词组进行分词和匹配,简而言之:如果“中国”是搜索关键字,那么它只会匹配索引表中对应字段中包含“ 中国 ”这样的词组,而包含“中”或者“国”的汉字不会被匹配, 记住这里面前后都有空格分开。同样的,如果创建的索引中数据有“我是中国人” ,那么要根据“中国“这个关键字根本匹配不到,因为SimpleAnalyzer 这个分词器只会去匹配 以空格分开的词组,所以要想匹配成功,那么添加索引的数据应该改为“我是 中国 人”,这样才会被检索到。

所以所以,要想使用”男“这个关键字匹配成功,就需要在添加索引的时候 改为”男 的“才可以。

既然中文汉字 是这样,试试看英文字母 是否亦如此。

果不其然:

<1>如果录入name字段的索引为”chenghui“  关键字指定为“cheng”搜不到;

<2>如果录入name字段的索引为”cheng hui“  关键字指定为“cheng”可以搜到;

<3>如果录入name字段的索引为”cheng hui“  关键字指定为“Cheng”搜不到;

<4>如果录入name字段的索引为”Cheng hui“  关键字指定为“Cheng”搜不到;

<5>如果录入name字段的索引为”Cheng hui“  关键字指定为“cheng”可以搜到;


由此可见: 索引录入的时候会统一转换成小写,但是关键字 没有转换成小写去匹配,这才导致大小写匹配不到的情况。

所以英文与数字和中文一样 不是那么人性化,并且我检索的时候连字母的大小写都没有区分,同时 数字 也是一样子的问题,   可见Lucene对其搜索的不完善性。

有没有解决方案呢? 有,上面例子使用的是SimpleAnalyzer 分词器,这个分词器是一段一段话进行分,现在介绍另外一个分词器StandardAnalyzer分词器,标准分词拿来分中文和ChineseAnalyzer一样的效果。

把上述代码中传递的分词器对象换成 new StandardAnalyzer(Version.LUCENE_36) ,试试效果,发现 StandardAnalyzer 在 SimpleAnalyzer 的基础上进行了优化,遗憾的是只是中文方面的,比如:

<1>如果录入sex索引为”男的“  关键字指定为“男” 可以搜到;

但是仅仅这样,远远不能满足全文检索的需求,这就需要使用更加高级的分词器来实现该功能。

实战 Lucene,Lucene 简介

 lucence  实战 Lucene,Lucene 简介已关闭评论
6月 162014
 

IBM developer上看到的文章,分享下:

Lucene 简介

Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。

目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

图 1 表示了搜索应用程序和 Lucene 之间的关系,也反映了利用 Lucene 构建搜索应用程序的流程:

图 1. 搜索应用程序和 Lucene 之间的关系

图 1. 搜索应用程序和 Lucene 之间的关系

索引和搜索

索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。为什么索引这么重要呢,试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene 采用的是一种称为反向索引(inverted index)的机制。反向索引就是说我们维护了一个词 / 短语表,对于这个表中的每个词 / 短语,都有一个链表描述了有哪些文档包含了这个词 / 短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。我们将在本系列文章的第二部分详细介绍 Lucene 的索引机制,由于 Lucene 提供了简单易用的 API,所以即使读者刚开始对全文本进行索引的机制并不太了解,也可以非常容易的使用 Lucene 对你的文档实现索引。

对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。

Lucene 软件包分析

Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。

Package: org.apache.lucene.document

这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field。这样,每一个文档最终被封装成了一个 Document 对象。

Package: org.apache.lucene.analysis

这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。

Package: org.apache.lucene.index

这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。

Package: org.apache.lucene.search

这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。

一个简单的搜索应用程序

假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。为了实现这种功能,我们首先利用 Lucene 对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所要查找的文档。通过这个例子读者会对如何利用 Lucene 构建自己的搜索应用程序有个比较清楚的认识。

建立索引

为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:

Document

Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。

Field

Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。

Analyzer

在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。

IndexWriter

IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。

Directory

这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。

熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单 1 给出了对某个目录下的文本文件建立索引的源代码。

清单 1. 对文本文件建立索引
package TestLucene;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
/**
* This class demonstrate the process of creating index with Lucene
* for text files
*/
public class TxtFileIndexer {
     public static void main(String[] args) throws Exception{
     //indexDir is the directory that hosts Lucene's index files
     File   indexDir = new File("D:luceneIndex");
     //dataDir is the directory that hosts the text files that to be indexed
     File   dataDir  = new File("D:luceneData");
     Analyzer luceneAnalyzer = new StandardAnalyzer();
     File[] dataFiles  = dataDir.listFiles();
     IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);
     long startTime = new Date().getTime();
     for(int i = 0; i < dataFiles.length; i++){
          if(dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")){
               System.out.println("Indexing file " + dataFiles[i].getCanonicalPath());
               Document document = new Document();
               Reader txtReader = new FileReader(dataFiles[i]);
               document.add(Field.Text("path",dataFiles[i].getCanonicalPath()));
               document.add(Field.Text("contents",txtReader));
               indexWriter.addDocument(document);
          }
     }
     indexWriter.optimize();
     indexWriter.close();
     long endTime = new Date().getTime();

     System.out.println("It takes " + (endTime - startTime)
         + " milliseconds to create index for the files in directory "
         + dataDir.getPath());
     }
}

在清单 1 中,我们注意到类 IndexWriter 的构造函数需要三个参数,第一个参数指定了所创建的索引要存放的位置,他可以是一个 File 对象,也可以是一个 FSDirectory 对象或者 RAMDirectory 对象。第二个参数指定了 Analyzer 类的一个实现,也就是指定这个索引是用哪个分词器对文挡内容进行分词。第三个参数是一个布尔型的变量,如果为 true 的话就代表创建一个新的索引,为 false 的话就代表在原来索引的基础上进行操作。接着程序遍历了目录下面的所有文本文档,并为每一个文本文档创建了一个 Document 对象。然后把文本文档的两个属性:路径和内容加入到了两个 Field 对象中,接着在把这两个 Field 对象加入到 Document 对象中,最后把这个文档用 IndexWriter 类的 add 方法加入到索引中去。这样我们便完成了索引的创建。接下来我们进入在建立好的索引上进行搜索的部分。

搜索文档

利用 Lucene 进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene 提供了几个基础的类来完成这个过程,它们分别是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。

Query

这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。

Term

Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。

TermQuery

TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。

IndexSearcher

IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。

Hits

Hits 是用来保存搜索的结果的。

介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了,清单 2 给出了完成搜索功能所需要的代码。

清单 2 :在建立好的索引上进行搜索
 package TestLucene;
 import java.io.File;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Hits;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.FSDirectory;
 /**
 * This class is used to demonstrate the
 * process of searching on an existing
 * Lucene index
 *
 */
 public class TxtFileSearcher {
	 public static void main(String[] args) throws Exception{
	    String queryStr = "lucene";
	    //This is the directory that hosts the Lucene index
        File indexDir = new File("D:luceneIndex");
        FSDirectory directory = FSDirectory.getDirectory(indexDir,false);
        IndexSearcher searcher = new IndexSearcher(directory);
        if(!indexDir.exists()){
        	 System.out.println("The Lucene index is not exist");
        	 return;
        }
        Term term = new Term("contents",queryStr.toLowerCase());
        TermQuery luceneQuery = new TermQuery(term);
        Hits hits = searcher.search(luceneQuery);
        for(int i = 0; i < hits.length(); i++){
        	 Document document = hits.doc(i);
        	 System.out.println("File: " + document.get("path"));
        }
	 }
 }

在清单 2 中,类 IndexSearcher 的构造函数接受一个类型为 Directory 的对象,Directory 是一个抽象类,它目前有两个子类:FSDirctory 和 RAMDirectory. 我们的程序中传入了一个 FSDirctory 对象作为其参数,代表了一个存储在磁盘上的索引的位置。构造函数执行完成后,代表了这个 IndexSearcher 以只读的方式打开了一个索引。然后我们程序构造了一个 Term 对象,通过这个 Term 对象,我们指定了要在文档的内容中搜索包含关键词”lucene”的文档。接着利用这个 Term 对象构造出 TermQuery 对象并把这个 TermQuery 对象传入到 IndexSearcher 的 search 方法中进行查询,返回的结果保存在 Hits 对象中。最后我们用了一个循环语句把搜索到的文档的路径都打印了出来。 好了,我们的搜索应用程序已经开发完毕,怎么样,利用 Lucene 开发搜索应用程序是不是很简单。

总结

本文首先介绍了 Lucene 的一些基本概念,然后开发了一个应用程序演示了利用 Lucene 建立索引并在该索引上进行搜索的过程。希望本文能够为学习 Lucene 的读者提供帮助。

转自:http://www.ibm.com/developerworks/cn/java/j-lo-lucene1/

LBS中附近的人实现简介

 lucence  LBS中附近的人实现简介已关闭评论
6月 162014
 

LBS中附近的人一般实现有以下几种:

  1. 数据库空间索引(Spatial Indexing)
    主流数据库(MongoDB, MySQL 5.0+、Oracle、PostgreSQL、SQL Server) 都在不同程度上支持欧空间索引,其中有一个类型就是 Point,可以用于存储每个用户所处位置的经纬度。
    有的数据库厂家直接提供了 OpenGIS 标准函数,最方便的就是 DISTANCE,直接按照 DISTANCE 排序。
              其中MongoDB的2d索引在计算附近时相当方便
  2. 传统数据库索引
    存储用户登入字段主要包括 userId,lat,lng。分别代表用户 ID、最近一次 check-in 的经度、纬度。
    lat/lng 建立复合索引。
    然后通过手机的定位,得到自己的位置,比如记为 myLat,myLng。
    代码如下,先做一个计算,算出 1km 所对应的经纬度范围:
    double range = 180 / Math.PI * 1 / 6372.797; //里面的 1 就代表搜索 1km 之内,单位km
    double lngR = range / Math.cos(myLat * Math.PI / 180.0);
    double maxLat = myLat + range;
    double minLat = myLat – range;
    double maxLng = myLng + lngR;
    double minLng = myLng – lngR;
    然后执行 SQL :
    SELECT xxxx FROM checkinTable WHERE ((lat BETWEEN ? AND ?) AND (lng BETWEEN ? AND ?)) LIMIT 100
    这四个问号,分别代入变量
    minLat、maxLat、minLng、maxLng
    然后就可以查询得到结果
    但是,这样得到的结果不是有序的。
    如果要排序,在程序代码(比如 app 客户端)执行。
    不建议在 SQL 层上执行,因为上述的那个 SQL 是可以用到索引进行查询的,一旦引入排序后,索引就无法发挥作用,从而会影响效率。
  3. Lucene有类似的包,搜索Lucene Spatial会有结果的。lucene端做好了。速度还行,容忍性低的话可以去该spatial包代码