博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Search(Solr)
阅读量:6608 次
发布时间:2019-06-24

本文共 12897 字,大约阅读时间需要 42 分钟。

hot3.png

Jetty

jetty启动时注册一个QueuedThreadPool和一些connector和monitor,并初始化一个WebAppContext/ServletContextHandler,同时注册一个LifeCycleListenerLifeCycleListener启动时,注册默认servlet和filter,和扩展的servlet和filter, 并将SolrDispatchFilter注册给WebAppContext/ServletContextHandlerSolrDispatchFilter包含一个solr的CoreContainer容器,该容器管理所有的solr coresSolrDispatchFilter的CoreContainer包含一些管理solr cores的工具,包括寻找core逻辑,注册core的逻辑,管理core的插件,以及处理core的插件(即各种SolrRequestHandler)SolrDispatchFilter的doFilter方法处理请求回应,主要是委托给HttpSolrCall来处理请求回应,HttpSolrCall依据url pattern来寻找对应的SolrRequestHandler来处理请求回应

 

Solr

   core/collection

   Schema&Document&Field

    solr的基本单元信息是document,document是一组描述事物的数据.documents是由字段组成的.字段可以更多的指定模块信息.字段可以包含不同种类的数据,一个name字段可以是text(字符数据), 也可以是一个浮点数,如6或者9.5,所以这个字段的定义比较灵活.但是如果恰当的定义字段,会提高查询效率.    可以通过指定solr的字段类型来告诉字段数据的类型.这个字段类型告诉solr如何解释这个字段,并且如何去查询.    当添加一个document时,solr会从document的字段中拿到数据信息并添加到索引中去.当执行查询时,solr会快速查询索引,返回匹配的文档(document)结果集.

  FieldType

字段类型元素fieldType包含4个信息的类型:name,class-实现类的名称,analyzer-用于字段类型的分析,即一些字段属性.

  Analyzers&Tokenizer&Filter

    字段分析器Analyzers即用于文档索引也用于查询.一个分析器检查字段的文本,并生成一个token流.分析器可能是一个单独的类,也可能是一系列的tokenizer和filter的组合.    分词器把字段数据分解成词汇单元或者tokens,过滤器(filters)检查tokens流,并且保持它们,转换它们,去除它们,或者创建一个新的token.分词器和过滤器可能会结合来形成管道,链条--这一个的输出就是下一个的输入.这样一个分词器和过滤器的序列叫做分析器(analyzer).分析器的结果输出用于匹配查询结果或者是建立索引.    尽管分析处理在索引和查询中都用到.相同的分析处理不必同时用于操作。对于索引,你想要简单化,规范化,词语化.例如,设置所有的字母都小写化,消除标点和重音,提取单词的词干等等.这样做可以增加召回原因.例如 "ram", "Ram" and "RAM"均匹配单词"ram".为了提高查询时间精度,过滤器(filter)可以缩小匹配范围.    分词处理程序输出的tokens定义了那个字段的值或术语,在添加新的文档时可以用于建立索引,或者识别在查询时哪个文档包含这些词(术语).

  Field&CopyFiled&DynamicField

    字段定义,提供一个名称和字段类型,也可以提供一些选项来覆盖字段类型的选项    复制字段,可以对单个的字段输入信息应用几个不同的字段类型.    动态字段允许solr索引没有在schema.xml中明确定义的字段

 

 data/Index

 Directory&Segment

索引目录Directory, 即Lucene中对索引目录的一个抽象lucene的索引目录    StandardDirectoryFactory  根据系统环境选择最佳读写方式	NIOFSDirectory  使用NIO方式读写索引。在windows下这个不是最优,主要原因:在windows下java nio存在bug。	SimpleFSDirectory 简单的磁盘存放,根据上面方法条件判断,在当MMapDirectory无法使用的时候,如果是Windows操作系统,推荐磁盘存储的模式。	此种模式,会有大量的磁盘IO,因此索引的创建和检索严重依赖磁盘性能。		RAMDirectory 这种内存存储方式,它主要用来存放非持久化索引的,也就意味程序关闭,索引就丢失了。	MMapDirectory  内存映射索引模式,一部分放在内存,一部分放在磁盘,但是需要操作系统支持(Swap),最好是64位系统和64位JVM,这样内存才能达到最大的应用。		NRTCachingDirectory (Near Real Time (NRT) Indexing)这是一种内存加磁盘存储的模式,主要用在实时搜索的场景,这在高版本的lucene才有。在solr默认的索引存储目录就是它solr增加的索引目录	HdfsDirectory 把索引存放到hdfs上的,它的使用场景就是索引是海量的。一般不是大数据,不会把数据放到hdfs上。	BlockDirectory 它把索引分成块,在分布式存储的一种概念,一切数据的存储都是block。org.apache.lucene.index.DirectoryReader:负责管理多个索引段org.apache.lucene.index.SegmentReader:负责读取某一个索引段的所有文件org.apache.lucene.index.SegmentInfos:封装了某个索引目录下的所有索引段文件信息,主要跟文件系统打交道org.apache.lucene.index.FieldInfos.FieldInfos:域信息org.apache.lucene.index.TermInfosReader.TermInfosReader:倒排表org.apache.lucene.index.SegmentNorms:主要是加载存储在标准化因子(.nrm)文件

  DocValues

  在solr4.2以后,引入了一个令人兴奋的功能,一种非常有效的索引方式:DocValue. 这个功能在lucene存在已经一段时间了,但是还没有在solr中使用.  标准的建立索引方式是一中倒排序索引方式,这种方式就是对索引中的所有文档的词语(terms)构造一个列表,挨着term是一个词语(term)所属文档的列表(同样包含词语在一篇文档中出现的次数).这种方式会使搜索速度很快,因为用户通过词语来搜索的,有一个准备好的词语到文档关系的值会使查询处理非常快.  对于其他常见的搜索相关的功能,如排序,分面,高亮.这种方法并不是很有效.这个分面工具,必须查找每篇文档中的每一个词语,然后组成结果集列表,抽取文档的id用来构建分面结果列表.在solr中,这主要是在内存中,并且加载比较慢.(主要依赖于文档数,词数terms等.)  在lucene4.0中,引入了一个新的方法,DocValue字段现在是一个以列为主的字段,具有在索引的时候构建的文档到值(document-to-value)的映射.这个方法保证减轻了一些字段缓存的内存要求,并且是查找分面,排序,分组速度更快.docValues和document的stored=ture存储的值,都是正排索引,单也是有区别的   DocValues是面向列的存储方式,stored=true是面向行的存储方式,如果通过fieldid取列的值可定是用docValues的存储结构更高   Stored=true的存储方式是不会分词的,会将字段原值进行保存,而docValues的保存的值会进行分词DocValues有四种实现方式1.       Memory   实现类:org.apache.lucene.codecs.memory.MemoryDocValuesFormat   运行时正排数据会全部加载到内存中,这部分数据在内存中是压缩存储的2.       Direct   实现类:org.apache.lucene.codecs.memory.DirectDocValuesFormat   导入到内存中不压缩使用,这个实际使用的效果应该和老版本的fieldcache差不多3.       SimpleText   实现类:org.apache.lucene.codecs.simpletext.SimpleTextDocValuesFormat    这个一般不用在环境中使用    以上三种类型定义在lucene-codecs-5.3.0.jar的META-INF/services目录下4.       Lucene50(默认使用)    实现类:org.apache.lucene.codecs.lucene50.Lucene50DocValuesFormat    Lucene50定义存放在lucene-core-5.3.0.jar的META-INF/services目录下    Lucene50的实现方式和Memory的实现方式大同小异,支持的字段类型更加丰富    在lucene50中将docValues的值分成5种类型:        1.       Numeric        2.       Binary        3.       Sorted        4.       SortedSet        5.       SortedNumeric    类型是由Schema中的field类型决定的:        l  StrField或者UUIDField            如果字段不是多值字段,则类型是SORTED            如果是多值字段,则类型是SORTED_SET        l  数值字段Trie*或者EnumField            如MultiValue=false,则NUMERIC            如MultiValued=true,则SORTED_SET
如果在索引上要进行facet,group,highlight等查询尽量使用docValue

  DocIDSet

  Document

    uniqueKey元素一篇文档的唯一标记    全局的similarity声明可以指定一个自定义的similarity实现,用来让solr处理索引时使用.similarity可以直接通过关联一个无参构造器的类的名称来指定

  Schemaless模式

  schemaless模式是一组solr功能的集合,允许用户通过简单的索引例子数据快速构建一个有效的schema,而不需要手动的编辑schema.这些solr功能都是在solrconfig.xml中指定的.主要是:  schema管理:schema修改是通过Solr API 而不是手动修改来完成的.参考--在solrconfig中管理schema定义.  字段值class的猜测:明显的,不可见的字段运行是通过一组级联的基于值的解析器,这些解析器可以猜测字段值的java类,用来解析Boolean, Integer, Long, Float, Double, 和Date.  基于字段值的java类,自动schema字段添加

 

RequestHandler

    一个request handler就是一个请求处理插件,这个插件定义了在solr处理请求时的请求处理逻辑.    solr支持多种request handler.一些用于搜索处理查询,然而其他的用于管理任务,如索引的replication(复制).

  SearchHandler&QueryParser$ResponseWriter

    搜索查询会被request handler处理,搜索应用选择了一部分request handler作为默认请求处理程序.另外,应用也可以被配置来允许用户重写request handler.    为了处理搜索查询,request handler调用query parser,用于解释查询的条件和参数.不同的查询解析(query parser)支持不同的语法.默认的查询解析器时DisMax解析器.

  UpdateHandler

    索引处理器属于Request Handlers,用于添加,更新,删除索引中的文档.另外,使用Tika抽取富文档数据,使用Data Import Handler抽取结构化数据.solr自然也就支持 XML, CSV 和 JSON格式的结构化文档.    建立索引的过程:添加内容到solr索引中,如果有需要,修改内容或者删除它.通过添加内容到索引里边,我们使其内容可以搜索.    solr索引能够接收不同来源的数据,xml文件,逗号分隔值的(CVS)文件,数据库,普通格式文件如Word或者PDF.    有三种不同的方式来加载数据到索引中:      使用以Apache Tika为基础的Solr Cell框架,用于摄取二进制文件或者结构化文件,比如Office, Word, PDF,和其他所有格式.      通过发送HTTP请求到solr服务器来上传XML文件.      通过solr的java客户端API来写一个自定义的java应用来抽取数据.(如果你正在使用一个应用程序,如内容管理系统,使用java的客户端API也许是一个不错的选择.)    不管抽取数据的方法,有一个普通的带有基本数据结构的数据添加到索引中:一个document包含多个fields,每一个field包含一个name和content,content可能为空.其中一个field被设计为唯一主键ID.

 

 

pom.xml

org.apache.solr
solr-solrj
6.6.0

solr_server.java  + solr_core

public void startEmbeddedSolrJettyServer(){    String tmpSolrHome = "solrcore";  int port = 8985;  String context = "/solr";    JettySolrRunner jetty = new JettySolrRunner(tmpSolrHome, context, port);  jetty.start();    Thread.sleep(5 * 60 * 1000);}    SolrXmlConfig: solr.xml    SolrCore: xxxx    CoreDescriptor: xxxx/core.properties    SolrConfig: xxxx/conf/solrconfig.xml        PluginBag: requestHandler    IndexSchema: xxxx/conf/schema.xmlor solr_server.java  + solr_start + solr_jetty_server_packagepublic void startSolrJettyServer() {			System.setProperty("jetty.home", "server/");			System.setProperty("jetty.base", "server/");			System.setProperty("solr.solr.home", "server/solr/");			org.eclipse.jetty.start.Main jetty = new org.eclipse.jetty.start.Main();			String[] args = new String[]{"server/etc/jetty.xml", "server/etc/jetty-http.xml",""};			jetty.init(args);			jetty.start();						Thread.sleep(5 * 60 * 1000);}

solr_client.java 

public class Solr {		public SolrClient getCloudSolrClient() throws MalformedURLException {		String zkHost = "192.168.0.112:2181";		CloudSolrClient solrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build();		return solrClient;	}	public SolrClient getLBHttpSolrClient() throws MalformedURLException {		String solrUrls = "http://192.168.0.112:8985/solr,http://192.168.0.112:8986/solr";		LBHttpSolrClient lbclient = new LBHttpSolrClient.Builder().withBaseSolrUrls(solrUrls.split(",")).build();		lbclient.setSoTimeout(5 * 60 * 1000);		lbclient.setConnectionTimeout(30 * 1000);		return lbclient;	}	public SolrClient getHttpSolrClient() throws MalformedURLException {		String solrUrl = "http://192.168.0.112:8983/solr/images";		HttpSolrClient solrClient = new HttpSolrClient.Builder(solrUrl).build();		return solrClient;	}	public SolrQuery solrQuery() {		SolrQuery query = new SolrQuery();//		query.setQuery("*:*");		query.set("fl", "*,score");//		query.addFilterQuery("ASOFD: [* TO 1399631920000]");		// query.addFilterQuery("ASOFD:1399631918438");		// query.addFilterQuery("SOURCESECONDARYID:(\"8392342:801\", \"8386910:800\")");		// query.addFilterQuery("SNAPSHOTDATE:20140822");		// query.addFilterQuery("SOURCESYSTEM:MUREXNY");		// query.addFilterQuery("-TRADESTATUS:\"DEAD SRC\"");		// query.addFilterQuery("-TRADESTATUS:\"DEAD\"");		// query.addFilterQuery("ASOFD:[1408666130000 TO *]");		// query.setParam("fl", "TRADE_URN,SNAPSHOTDATE");		//query.setStart(0);		//query.setRows(10);		return query;	}	public Stream
> query(SolrClient solrClient, SolrQuery query) throws Exception { Stream
> results = null; QueryResponse queryResponse; queryResponse = solrClient.query(query); results = queryResponse.getResults().stream().map( document -> { return toMap(document);} ); return results; } public SolrDocument query(SolrClient solrClient, String id) { SolrDocument result = null; SolrDocumentList results = null; SolrQuery query = new SolrQuery(); query.setQuery("id:" + id); try { QueryResponse queryResponse = solrClient.query(query); System.out.println("Response:" + queryResponse); results = queryResponse.getResults(); System.out.println("Response list size:" + results.size()); if (results.size() > 0) { result = results.get(0); } } catch (SolrServerException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } private void delete(SolrClient solrClient, String id) { try { UpdateResponse updateResponse = solrClient.deleteById(id); System.out.println("Insert Response:" + updateResponse); UpdateResponse commitResponse = solrClient.commit(false, false, true); System.out.println("CommitResponse:" + commitResponse); } catch (SolrServerException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void index(SolrClient solrClient, SolrInputDocument document) { try { UpdateResponse response1 = solrClient.add(document); UpdateResponse commitResponse = solrClient.commit(false, false, true); } catch (SolrServerException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public SolrInputDocument toInputDocument(Map
kvs) { SolrInputDocument document = new SolrInputDocument(); for (Map.Entry
item : kvs.entrySet()) { document.addField(item.getKey(), item.getValue()); } return document; } public SolrDocument toDocument(Map
kvs) { SolrDocument document = new SolrDocument(); for (Map.Entry
item : kvs.entrySet()) { document.addField(item.getKey(), item.getValue()); } return document; } public Map
toMap(SolrInputDocument document) { Map
kvs = new HashMap
(); for (Entry
item : document.entrySet()) { kvs.put(item.getKey(), item.getValue().getValue()); } return kvs; } public Map
toMap(SolrDocument document) { Map
kvs = new HashMap
(); for (Entry
item : document.entrySet()) { kvs.put(item.getKey(), item.getValue()); } return kvs; }}

test.java

@Test	public void testIndex() throws MalformedURLException{		Solr solr = new Solr();				SolrClient client = solr.getHttpSolrClient();		Map
doc = new HashMap<>(); doc.put("id", "/home/zhaomeng/Pictures/zm_student.jpg"); doc.put("title", "zm_student"); doc.put("imgurl", "/home/zhaomeng/Pictures/zm_student.jpg"); solr.index(client, solr.toInputDocument(doc)); doc = new HashMap<>(); doc.put("id", "/home/zhaomeng/Pictures/zm_worker1.jpg"); doc.put("title", "worker1"); doc.put("imgurl", "/home/zhaomeng/Pictures/zm_worker1.jpg"); solr.index(client, solr.toInputDocument(doc)); doc = new HashMap<>(); doc.put("id", "/home/zhaomeng/Pictures/zm_worker2.jpg"); doc.put("title", "worker2"); doc.put("imgurl", "/home/zhaomeng/Pictures/zm_worker2.jpg"); solr.index(client, solr.toInputDocument(doc)); } @Test public void testSearch() throws Exception{ Solr solr = new Solr(); SolrClient client = solr.getHttpSolrClient(); SolrQuery query = solr.solrQuery(); query.setRequestHandler("/lireq"); query.add("feature", ImageHelper.extractCEDD("/home/zhaomeng/Pictures/zhaomeng.png")); query.add("field", "ce"); //query.add("extract", "http://192.168.0.112/zhaomeng.png"); query.add("hashes", "12 23"); QueryResponse queryResponse; queryResponse = client.query(query); System.out.println(queryResponse); }

or

http://localhost:10000/solr/lire/update?wt=xml&stream.body=
5432a
&commit=truehttp://localhost:10000/solr/lire/update?wt=xml&stream.url=http://xxxx/xxx.htmlhttp://localhost:10000/solr/lire/update?wt=xml&stream.body=
id:298253
&commit=truehttp://localhost:10000/solr/lire/update?wt=xml&stream.body=
*:*
&commit=true

 

转载于:https://my.oschina.net/igooglezm/blog/1503428

你可能感兴趣的文章
GETTING UP AND RUNNING WITH NODE.JS, EXPRESS, JADE, AND MONGODB
查看>>
求二叉树第K层节点的个数
查看>>
MySQLs数据库建外键时自动跑到缩影处,真奇怪
查看>>
static关键字
查看>>
js 合并多个对象 Object.assign
查看>>
Java 反射机制
查看>>
Unity 碰撞检测中碰撞器与触发器的区别
查看>>
Elasticsearch配置文件说明
查看>>
初识java
查看>>
temporary Object and destructor
查看>>
xcode - 移动手势
查看>>
细说浏览器特性检测(1)-jQuery1.4添加部分
查看>>
古中国数学家的计算力真是惊人
查看>>
Java基础-算术运算符(Arithmetic Operators)
查看>>
C#编程(四十七)----------集合接口和类型
查看>>
【转】关于大型网站技术演进的思考(十二)--网站静态化处理—缓存(4)
查看>>
积跬步,聚小流------Bootstrap学习记录(1)
查看>>
HDUPhysical Examination(贪心)
查看>>
HTML5 FileAPI
查看>>
使用tdcss.js轻松制作自己的style guide
查看>>