elasitcsearch中有没有比较字符长度的条件?

Elasticsearchjoeywen 回复了问题 • 2 人关注 • 1 个回复 • 2705 次浏览 • 2016-07-01 19:04 • 来自相关话题

es粗排速度很慢

Elasticsearchstab 回复了问题 • 2 人关注 • 1 个回复 • 2752 次浏览 • 2016-07-01 11:07 • 来自相关话题

marvel插件过期了,有其他好用的插件吗

ElasticsearchRoy 回复了问题 • 3 人关注 • 2 个回复 • 3646 次浏览 • 2016-06-30 16:20 • 来自相关话题

Correlation问题

Elasticsearchbillzy 回复了问题 • 2 人关注 • 2 个回复 • 2189 次浏览 • 2016-06-30 10:45 • 来自相关话题

我的问题:redis->logstash->mysql

回复

Logstashlongjq 回复了问题 • 1 人关注 • 1 个回复 • 3025 次浏览 • 2016-06-29 18:46 • 来自相关话题

ES2.1中@timestamp的mapping冲突

Elasticsearchsp42 回复了问题 • 4 人关注 • 4 个回复 • 5186 次浏览 • 2016-06-29 13:38 • 来自相关话题

failed to find analyzer type [mmseg_maxword] or tokenizer

Elasticsearchzplzpl 回复了问题 • 5 人关注 • 4 个回复 • 4197 次浏览 • 2016-06-27 17:03 • 来自相关话题

elasticsearch.yml 定义的分析器 failed to find analyzer

回复

Elasticsearchzplzpl 回复了问题 • 1 人关注 • 1 个回复 • 2734 次浏览 • 2016-06-27 16:47 • 来自相关话题

关于主分片以及副本数量设定

回复

Elasticsearch匿名用户 回复了问题 • 1 人关注 • 1 个回复 • 2630 次浏览 • 2016-06-25 19:27 • 来自相关话题

es删除一个集群的某一节点

Elasticsearchflowaters 回复了问题 • 2 人关注 • 1 个回复 • 3644 次浏览 • 2016-06-25 19:23 • 来自相关话题

MapperParsingException[Failed to parse mapping [_default_]:

ElasticsearchJay 回复了问题 • 3 人关注 • 4 个回复 • 4093 次浏览 • 2016-06-24 16:08 • 来自相关话题

Lucene5.5入门第十篇完结篇——使用Highlighter使关键词高亮

Lucenekl 发表了文章 • 0 个评论 • 3180 次浏览 • 2016-06-24 11:27 • 来自相关话题

前言

我们在使用百度和谷歌等搜索引擎的时候,你会发现,搜索引擎会把和我们输入的关键字以红色的字体显示,来突出显示结果的准确性,这就是高亮显示的使用场景

准备

使用Highlighter需要导入相应的jar包,maven项目可以加入如下依赖

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>5.5.0</version>
</dependency>

直接看代码


/**
* @author kl by 2016/3/19
* @boke www.kailing.pub
*/
public class FieldSetBoostTest {
//索引目录
String indexDir="E:\\LuceneIndex";
//测试数据
String theme="中国";
String []title={"中国是一个伟大的国家","我爱你的的祖国,美丽的中国","是什么,中国令美日等国虎视眈眈"};
/**
* Lucence5.5返回IndexWriter实例
* @param directory
* @return
*/
public IndexWriter getIndexWriter(Directory directory){
Analyzer analyzer=new CJKAnalyzer();//中日韩二元分词
IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer);
IndexWriter writer=null;
try {
writer =new IndexWriter(directory,writerConfig);
}catch (Exception e){
e.printStackTrace();
}
return writer;
}
public Directory getDirctory(String indexDir){
Directory directory=null;
try {
directory=FSDirectory.open(Paths.get(indexDir));
}catch (IOException e){
e.printStackTrace();
}
return directory;
}
/**
* 创建索引不加权
* @throws Exception
*/
public void Indexer()throws Exception{
IndexWriter writer=getIndexWriter(getDirctory(indexDir));
Document doc=null;
for(String str:title){
doc=new Document();
//Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词
doc.add(new StringField("theme",theme, Field.Store.YES));
Field field=new TextField("title",str, Field.Store.YES);
doc.add(field);
writer.addDocument(doc);
}
writer.close();
}

/**
* 关键命中词高亮输出处理
* @param query
* @param context
* @return
* @throws Exception
*/
public static String getHighlighterString(Query query,String context)throws Exception{
//对促成文档匹配的实际项进行评分
QueryScorer scorer=new QueryScorer(query);
//设置高亮的HTML标签格式
Formatter simpleHTMLFormatter=new SimpleHTMLFormatter("","");
//实例化高亮分析器
Highlighter highlighter=new Highlighter(simpleHTMLFormatter,scorer);
//提供静态方法,支持从数据源中获取TokenStream,进行token处理
TokenStream tokenStream=new CJKAnalyzer().tokenStream("title", new StringReader(context));
return highlighter.getBestFragment(tokenStream, context);
}
@Test
public void searcherTest()throws Exception{
// Indexer();
IndexReader reader= DirectoryReader.open(getDirctory(indexDir));
IndexSearcher is=new IndexSearcher(reader);
System.out.println("总的文档数:"+reader.numDocs());
QueryParser qp=new QueryParser("title",new CJKAnalyzer());
String q="中国";
Query query=qp.parse(q);
TopDocs tDocs=is.search(query,11);
System.out.println("查询-》"+q+"《-总共命中【"+tDocs.totalHits+"】条结果");
for (ScoreDoc scoredoc:tDocs.scoreDocs){
Document doc = is.doc(scoredoc.doc);
String context=doc.get("title");
if(context!=null){
System.out.println(getHighlighterString(query,context));
}

}
}
}
查询效果如下:

原文地址:http://www.kailing.pub/article/index/arcid/82.html

Lucene5.5入门第九篇——使用searchafter方法实现分页查询

Lucenekl 发表了文章 • 0 个评论 • 3473 次浏览 • 2016-06-24 11:25 • 来自相关话题

前言

任何数据量大的情况下,取数据的时候都需要做分页的处理,比如我们百度的时候,结果往往有上千万的结果,而当前呈现在的只有几页的内容,这就是分页的场景,lucene也提供了分页查询的支持

认识searchafter

使用IndexSearcher的searchafter方法可以轻松实现分页查询,如下图



searchafter有多个重载的方法,其中有些searchafter方法Lucene已不推荐使用了,用的多的就searchAfter(final ScoreDoc after, Query query, int numHits)

它有三个形参,分别是

after:上一页最后一个ScoreDoc;

query:query接口实现类的对象,query对象可以通过QueryParser类来创建,也可以自己new Query接口的某一个特定接口实现类;

numHits:每页显示的条数

searchafter官方文档说明地址

重点在下面

/**
* Created by 小陈 on 2016/3/25.
*/
public class IndexerPaging {
//测试数据,模拟数据库表结构
private static String[] ids={"1","2","3","4","5","6"}; //用户ID
private static String [] names={"kl","kl","kl","kl","kl","fds"};
private static String [] describes={"shi yi ge mei nan zi","Don't know","Is an idiot\n","Is an idiot\n","Is an idiot\n","Is an idiot\n"};
//索引存储地址
private static String indexDir="E:\\javaEEworkspace\\LuceneDemo\\LuceneIndex";

/**
* 获取操作索引实体,并添加测试数据
* @param indexDir 索引存储位置
* @return
* @throws Exception
*/
public static void getIndexWriter(String indexDir)throws Exception{
IndexWriterConfig writerConfig=new IndexWriterConfig(getAnalyzer());
IndexWriter indexWriter=new IndexWriter(FSDirectory.open(Paths.get(indexDir)),writerConfig);
Document document=new Document();
//Field.Store.YES或者NO(存储域选项)
//设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原
//设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get)
for(int i=0;i1){
int pageIndexLast=(pageIndex-1)*pageSize-1;
TopDocs hits=searcher.search(query,pageIndexLast);
if(hits.totalHits>=pageIndexLast)
return hits.scoreDocs[pageIndexLast];

}
return null;
}

public static void searcher(String indexDir,String q,int pageIndex,int pageSize)throws Exception{
Directory directory= FSDirectory.open(Paths.get(indexDir));
IndexReader reader= DirectoryReader.open(directory);
IndexSearcher indexSearcher=new IndexSearcher(reader);
QueryParser queryParser=new QueryParser("names",new StandardAnalyzer());
Query query=queryParser.parse(q);
//分页查询
TopDocs hits= indexSearcher.searchAfter(getPageLastScoreDoc(pageIndex,pageSize,query,indexSearcher),query,pageSize);//查询首次的30条
System.out.println("匹配 "+q+"查询到"+hits.totalHits+"个记录");
for (ScoreDoc scoreDoc:hits.scoreDocs){
Document doc=indexSearcher.doc(scoreDoc.doc);
System.out.println(doc.get("describes"));//打印Document的fileName属性
}
reader.close();
directory.close();//关闭连接
}
/**
* 得到默认分词器
* @return
*/
public static Analyzer getAnalyzer(){
return new StandardAnalyzer();
}

@Test
public void Test()throws Exception{
// getIndexWriter(indexDir);
searcher(indexDir,"kl",1,10);//查询测试
}

}
原文地址:http://www.kailing.pub/article/index/arcid/80.html

Lucene5.5入门第八篇——使用QueryParser实现高级查询

Lucenekl 发表了文章 • 0 个评论 • 3043 次浏览 • 2016-06-24 11:23 • 来自相关话题

前言

为了解决复杂的查询业务,Lucene给我们提供了一个查询语义分析器,一套完整的语法规则,能够满足大部分的查询需求,而不用关心底层是使用什么Query实现类,就好比写sql一样。 Lucene推荐我们使用QueryParser,而不是各种Query的实现类。但是,QueryParser不能满足所有的查询有求,比如多文档域联合查询 。有时候还是需要使用到Query的相关实现类,好了,下面我们就来看看QueryParser能够解析什么语法,解决什么问题,以及多文档域的查询


直接上代码

每个语法都可以多测试一遍,看看结果,能够加深你的理解,因为这边测试的实在是多,测试结果我就不贴了;

ps:各个查询语义可以交叉使用的,下面代码有部分也用到了,但是这边因为是写的例子,为了能更好的区分每个语义的作用,所有没有做太多的尝试

/**
* @author kl by 2016/3/20
* @boke www.kailing.pub
*/
public class QueryTest {
//索引目录
String indexDir="E:\\LuceneIndex";
//测试数据目录
String dataDir="E:\\LuceneTestData";
/**
* Lucence5.5返回IndexWriter实例
* @param directory
* @return
*/
public IndexWriter getIndexWriter(Directory directory){
Analyzer analyzer=new StandardAnalyzer();
IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer);
IndexWriter writer=null;
try {
writer =new IndexWriter(directory,writerConfig);
}catch (Exception e){
e.printStackTrace();
}
return writer;
}
public Directory getDirctory(String indexDir){
Directory directory=null;
try {
directory= FSDirectory.open(Paths.get(indexDir));
}catch (IOException e){
e.printStackTrace();
}
return directory;
}
@Test
public void TestIndexer()throws Exception{
File[] files= new File(dataDir).listFiles();
IndexWriter writer=getIndexWriter(getDirctory(indexDir));
for(File file:files){
Document doc=new Document();
doc.add(new TextField("filePath",file.getCanonicalPath(), Field.Store.YES));
doc.add(new TextField("context",new FileReader(file)));
writer.addDocument(doc);
}
System.out.println("总共添加了"+writer.numDocs()+"个文档");
writer.close();
}
@Test
public void testSearcher()throws Exception{
IndexReader reader= DirectoryReader.open(getDirctory(indexDir));
IndexSearcher searcher=new IndexSearcher(reader);
QueryParser queryParser=new QueryParser("context",new StandardAnalyzer());
Query queryw=queryParser.parse("Licensor");//完整匹配分词查询
/**
* 通配符 ?,*的使用
*/
Query queryy=queryParser.parse("Lice?sor");//使用?匹配单个字符查询
Query queryx=queryParser.parse("L*r");//使用*匹配多个字符查询
/**
* 布尔运算AND, OR,NOT,+,-的使用,注意:一定要是大写的AND和OR,NOT
*/
Query queryo=queryParser.parse("Licensor OR ce*");//使用OR联合多关键字查询,也可用空格代替OR
Query queryoo=queryParser.parse(" Licensor ce*");//这个和使用OR一样的效果
Query queryjia=queryParser.parse("+Licensor Wildcard");//+代表必须的条件,搜索文档必须包含Licensor 可能有Wildcard
Query querya=queryParser.parse("Licensor AND ce* AND Licenso?");//使用AND取多个关键字的并集查询
Query queryNot=queryParser.parse("'Lincensor Apache' NOT 'Apache Licensor'");//搜索Lincensor Apache而不是Apache Licensor
Query queryjian=queryParser.parse("'Lincensor Apache' - 'Apache Licensor'");//"-"同NOT的效果一样

/**
* 使用正则表达式查询
*/
Query queryRegular=queryParser.parse("/[Lab]icensor/");//这个匹配Lincensor,aicensor,bicensor分词
Query queryRegularr=queryParser.parse("/[Lab]icenso[a-z]/");//根据需要可以更灵活的使用
/**
* 使用~模糊匹配查询
* 这个要和*号的用法区分下,*号完整通配多个字符查询,而~不是简单的通配,这个模糊匹配和Lucene的评分有关
*/
Query queryFuzzy=queryParser.parse("icensor~");//可以查到Licensor关键字,而queryParser.parse("icensor*")查不到
Query queryFuzzyparam=queryParser.parse("Licens~1");//~后面可加0-2的整数来制定模糊匹配度,默认不加为1
Query queryFuzzyParam=queryParser.parse("Licens cens ~0");//~还可以模糊匹配差异化N字符数的多个关键字
/**
* 范围查询,多用于数字和时间的查询
*/
Query queryRange =queryParser.parse("{abc TO Licens}");//{}abc与Licenszhi间的文件,不包含
Query queryRangex =queryParser.parse("[abc TO Licens]");//{}abc与Licenszhi间的文件,包含本身
/**
* 关键字加权处理查询
*/
//默认为1,可加权可降权,可通过加权处理给匹配的结果排序
Query queryBoosting =queryParser.parse("Licensor Wildcard^4 ");

/**
* Grouping组合查询
*/
Query queryGrouping =queryParser.parse("(+Licensor +Wildcard) AND easier");//可使用()组合多个条件查询

//ps: 查询部分字符需要转义处理,如(+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /)

/**
* 使用MultiFieldQueryParser进行多个文档域查询
*/
Map boost=new HashMap();
boost.put("filePath",1.5F);//设置文档域的权值
boost.put("context",2F);
QueryParser multiField=new MultiFieldQueryParser(new String[]{"filePath","context"},new StandardAnalyzer(),boost);
Query queryq=multiField.parse("lucenetestdata");

TopDocs topDocs= searcher.search(queryq,10);
System.out.println("查询结果共有"+topDocs.totalHits+"条");
for(ScoreDoc scoreDoc:topDocs.scoreDocs){
Document document=searcher.doc(scoreDoc.doc);
System.out.println(document.get("filePath")+"--评分:"+scoreDoc.score);
}
}

}
ps:代码中有大量注释,有些不一定理解到位了,深入了解 请参考官方说明:

https://lucene.apache.org/core ... rches
原文地址:http://www.kailing.pub/article/index/arcid/79.html

Lucene5.5入门第七篇——Lucene索引文档域加权

Lucenekl 发表了文章 • 0 个评论 • 3233 次浏览 • 2016-06-24 11:22 • 来自相关话题

前言

就拿百度说事吧,使用百度搜索引擎的时候,你会发现,卧槽,这什么玩意,前面的几个结果根本就不是老子要的东西,都是些推广的内容,而结果匹配度高的还排在老后面去了,百度这铲屎的干嘛吃的!这也不能怪百度,毕竟人家靠推广吃饭的,自然把交了钱的结果权值提高了 !这算文档域加权的使用场景吧

说明

所谓索引域加"权",就是根据需求的不同,对不同的关键值或者不同的关键索引分配不同的权值,因为查询的时候Lucene的评分机制和权值的高低是成正比的,这样权值高的内容更容易被用户搜索出来,而且排在前面。在Lucene3.x版本的时候可以给文档加权,到4.x版本后就取消了给文档加权了,就只有给文档域加权了,如果想达到给文档加权的效果,就要该文档的每个域都加权处理

ps:博主前篇博文谈过IKAnalyzer与paoding中文分词,今天我们使用的是可用于中日韩的二元分词器CJKAnalyzer

闲话少说,直接上代码,看结果


package com.kl.luceneDemo;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Paths;
/**
* @author kl by 2016/3/19
* @boke www.kailing.pub
*/
public class FieldSetBoostTest {
//索引目录
String indexDir="E:\\LuceneIndex";
//测试数据
String theme="中国";
String []title={"中国是一个伟大的国家","我爱你的的祖国,美丽的中国","是什么,中国令美日等国虎视眈眈"};
/**
* Lucence5.5返回IndexWriter实例
* @param directory
* @return
*/
public IndexWriter getIndexWriter(Directory directory){
Analyzer analyzer=new CJKAnalyzer();//中日韩二元分词
IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer);
IndexWriter writer=null;
try {
writer =new IndexWriter(directory,writerConfig);
}catch (Exception e){
e.printStackTrace();
}
return writer;
}
public Directory getDirctory(String indexDir){
Directory directory=null;
try {
directory=FSDirectory.open(Paths.get(indexDir));
}catch (IOException e){
e.printStackTrace();
}
return directory;
}
/**
* 创建索引不加权
* @throws Exception
*/
public void Indexer()throws Exception{
IndexWriter writer=getIndexWriter(getDirctory(indexDir));
Document doc=null;
for(String str:title){
doc=new Document();
//Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词
doc.add(new StringField("theme",theme, Field.Store.YES));
Field field=new TextField("title",str, Field.Store.YES);
doc.add(field);
writer.addDocument(doc);
}
writer.close();
}
/**
* 创建索引,指定文档域加权
* @throws Exception
*/
public void IndexerSetBoot()throws Exception{
IndexWriter writer=getIndexWriter(getDirctory(indexDir));
Document doc=null;
for(String str:title){
doc=new Document();
//Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词
doc.add(new StringField("theme",theme, Field.Store.YES));
Field field=new TextField("title",str, Field.Store.YES);
if(str.indexOf("是什么")!=-1)
field.setBoost(2);//提高权值
doc.add(field);
writer.addDocument(doc);
}
writer.close();
}
@Test
public void searcherTest()throws Exception{
IndexerSetBoot();
// Indexer();
IndexReader reader= DirectoryReader.open(getDirctory(indexDir));
IndexSearcher is=new IndexSearcher(reader);
System.out.println("总的文档数:"+reader.numDocs());
QueryParser qp=new QueryParser("title",new CJKAnalyzer());
Query query=qp.parse("中国");
TopDocs tDocs=is.search(query,11);//一次查询多少个结果
System.out.println("总共有【"+tDocs.totalHits+"】条结果");
for (ScoreDoc scoredoc:tDocs.scoreDocs){
Document doc = is.doc(scoredoc.doc);
System.out.println(doc.getField("title").stringValue());
}
}
}
加权和不加权的结果如下



原文地址:http://www.kailing.pub/article/index/arcid/77.html