第十六讲-Lucene高级进阶续一

合集下载

lucene学习

lucene学习

lucene学习1.基本概念信息检索(IR)是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。

文档:用于搜索的内容部件。

词汇单元:即分词。

词干提取器,如Snowball。

搜索质量主要由查准率(Preciion)和查全率(Recall)来衡量。

[1]P13语法检查器:Lucene的contrib目录提供了两个模块完成此功能。

查询对象:Lucene提供了一个称之为查询解析器(QueryParer),用它可以根据通用查询语法将用户输入的文本处理成查询对象。

查询搜索:査询检索索引并返回与査询语句匹配的文档,结果返回时按照査询请求来排序。

搜索查询组件涵盖了搜索引擎内部复杂的工作机制,Lucene正是如此,它为你完成这一切。

倒排索引:invertedinde某常见的搜索理论模型有如下3种。

■纯布尔模型(PureBooleanmodel)文档不管是否匹配查询请求,都不会被评分.在该模型下,匹配文档与评分不相关,也是无序的;一条查询仅获取所有匹配文档集合的一个子集。

■向量空间模型(Vectorpacemodel)查询语句和文档都是高维空间的向量模型,这里每一个独立的项都是一个维度。

查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到.■概率模型(Probabiliticmodel)在该模型中,采用全概率方法来计算文档和查询语句的匹配概率。

Lucene在实现上采用向量空间模型和纯布尔模型,并能针对具体搜索让你决定采用哪种模型。

最后,Lucene返回的文档结果必须用比较经济的方式展现给用户。

搜索范围:涉及分布式搜索,ApacheLucene项目下的Solr和Nutch 项目提供了对索引拆分和复制的支持,另Katta和Elaticearch。

1.1Lucene核心类概貌执行简单的索引过程需要用到以下几个类:■Inde某Writer■Directory■Analyzer■Document■FieldInde某Writer(写索引)是索引过程的核心组件。

Lucene入门+实现

Lucene入门+实现

Lucene⼊门+实现Lucene简介详情见:()lucene实现原理其实⽹上很多资料表明了,lucene底层实现原理就是倒排索引(invertedindex)。

那么究竟什么是倒排索引呢?经过Lucene分词之后,它会维护⼀个类似于“词条--⽂档ID”的对应关系,当我们进⾏搜索某个词条的时候,就会得到相应的⽂档ID。

不同于传统的顺排索引根据⼀个词,知道有哪⼏篇⽂章有这个词。

图解:Lucene在搜索前⾃⾏⽣成倒排索引,相⽐数据库中like的模糊搜索效率更⾼!Lucene 核⼼API索引过程中的核⼼类1. Document⽂档:他是承载数据的实体(他可以集合信息域Field),是⼀个抽象的概念,⼀条记录经过索引之后,就是以⼀个Document的形式存储在索引⽂件中的。

2. Field:Field 索引中的每⼀个Document对象都包含⼀个或者多个不同的域(Field),域是由域名(name)和域值(value)对组成,每⼀个域都包含⼀段相应的数据信息。

3. IndexWriter:索引过程的核⼼组件。

这个类⽤于创建⼀个新的索引并且把⽂档加到已有的索引中去,也就是写⼊操作。

4. Directroy:是索引的存放位置,是个抽象类。

具体的⼦类提供特定的存储索引的地址。

(FSDirectory 将索引存放在指定的磁盘中,RAMDirectory ·将索引存放在内存中。

)5. Analyzer:分词器,在⽂本被索引之前,需要经过分词器处理,他负责从将被索引的⽂档中提取词汇单元,并剔除剩下的⽆⽤信息(停⽌词汇),分词器⼗分关键,因为不同的分词器,解析相同的⽂档结果会有很⼤的不同。

Analyzer是⼀个抽象类,是所有分词器的基类。

搜索过程中的核⼼类1. IndexSearcher :IndexSearcher 调⽤它的search⽅法,⽤于搜索IndexWriter 所创建的索引。

2. Term :Term 使⽤于搜索的⼀个基本单元。

跟我学全文检索Lucene框架及应用(第1部分)

跟我学全文检索Lucene框架及应用(第1部分)

目录1.1全文检索引擎Lucene相关技术及应用(第1部分) (2)1.1.1站内搜索相关技术介绍 (2)1.1.2Apache Lucene全文检索引擎工具包 (3)1.1.3Lucene系统库及应用 (9)1.1.4索引管理相关的代码示例 (33)1.1全文检索引擎Lucene相关技术及应用(第1部分)1.1.1站内搜索相关技术介绍1、站内搜索的必要性在以往的网站建设,企业系统的搭建过程中,因为信息比较简单和信息的数量也比较少,站内搜索可能不是必要的功能。

而如今,信息量的增大,网站逻辑的复杂,企业自身对信息架构、管理、发布的需求,以及用户对信息的组织、查询、可寻性的要求越来越高,于是站内搜索的功能要求出现了。

而如果在Web应用系统中能够提供站内搜索,则能够很快的得到用户所要检索的信息,这样给用户提供了很大的方便。

2、和通用搜索引擎的区别谷歌、百度、搜搜等通用搜索引擎都会免费开放站内搜索功能,以嵌入网页代码的形式保持与搜索引擎机器人的沟通、爬取。

但采用此方法的主要弊病有如下三种:(1)这些通用搜索引擎不能及时、全部抓取网站最新页面内容。

这对电子商务网站信息(如价格、活动有效时间等)经常更新的特点来说是致命的,用户查到的可能是过时信息。

(2)既然是所谓通用引擎,其对搜索结果的展示也是通用的,没有差异性的。

其不能按照商城自身业务逻辑去做排序、过滤、展示是其最大的弱项。

(3)通用搜索,无法提供热词,搜索推荐词,关联词等功能,还需要二次开发,增加工作量和复杂度。

因此,站内搜索的出现也是有其具体原因和需求的,在搜索的精确度和效果上击败了通用搜索引擎。

1.1.2Apache Lucene全文检索引擎工具包1、Lucene(/)Lucene是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。

Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎——索引、分词、搜索三个主要的部分。

lucene对比中文近义词用法

lucene对比中文近义词用法

标题:探讨Lucene对比中文近义词用法1. 简介为了更好地理解Lucene对比中文近义词用法,我们首先需要了解Lucene的基本概念和中文近义词的特点。

Lucene是一个全文检索引擎库,它提供了丰富的API,可以用于构建强大的全文搜索功能。

而中文近义词则是指在中文语境中,表达相似意义的词语,这些词语在不同的语境中可能会有微小的差别,但整体的意思是相通的。

2. Lucene的基本原理和功能Lucene通过倒排索引的方式来快速定位文档中的关键词,从而实现全文搜索的功能。

它采用了分词器来处理文本,将文本分割成若干个独立的单词,并将这些单词进行索引。

在搜索时,用户输入的查询语句也经过相同的分词处理,再与索引进行匹配,最终返回相关的文档。

3. 中文近义词的特点在中文语境中,由于词语的复杂性和多义性,往往会存在大量的近义词。

这些近义词可能在不同的场景中有不同的使用方式,但它们的基本意思是一致的。

“喜欢”和“爱好”就是一对中文近义词,它们都表示喜爱或偏好的意思,只是在语感上有细微的区别。

4. Lucene对比中文近义词用法在使用Lucene进行搜索时,对于中文近义词的处理往往是一个挑战。

由于中文的特殊性,同一个词可能存在多种不同的表达方式,而传统的搜索引擎很难将它们准确地匹配在一起。

针对这一问题,Lucene提供了同义词扩展的功能,可以将一些近义词视作同一个词来处理。

这样一来,用户在搜索时无需考虑到所有的近义词,只需要输入其中一个,就能够搜索到相关的文档。

5. 个人观点和总结通过对Lucene对比中文近义词用法的探讨,我们可以发现,Lucene在处理中文近义词时的确存在一些挑战,但它也提供了相应的解决方案。

在实际应用中,我们可以根据具体的需求,合理地进行同义词扩展,以提升搜索结果的准确性和覆盖范围。

对于中文近义词的掌握也需要结合具体的语境和语气来理解,不能简单地进行机械替换。

Lucene对比中文近义词用法的探讨,有助于我们更好地理解和应用这一强大的全文搜索引擎库。

Lucene教程详解

Lucene教程详解

Lucene教程详解Lucene-3.0.0配置一、Lucene开发环境配置step1.Lucene开发包下载step2.Java开发环境配置step3.Tomcat安装step4.Lucene开发环境配置解压下载的lucene-3.0.0.zip,可以看到lucene-core-3.0.0.jar和lucene-demos-3.0.0.jar这两个文件,将其解压(建议放在安装jdk的lib文件夹内),并把路径添加到环境变量的classpath。

二、Lucene开发包中Demo调试控制台应用程序step1.建立索引>java org.apache.lucene.demo.IndexFiles [C:\Java](已经存在的任意文件路径)将对C:\Java下所有文件建立索引,同时,在当前命令行位置将生成“index”文件夹。

step2.执行查询>java org.apache.lucene.demo.SearchFiles将会出现“Query:”提示符,在其后输入关键字,回车,即可得到查询结果。

Web应用程序step1.将lucene-core-3.0.0.jar和lucene-demos-3.0.0jar这两个文件复制到安装Tomcat 的\common\lib中step2.解压下载的lucene-3.0.0.zip,可以看到luceneweb.war文件。

将该文件复制到安装Tomcat的\webappsstep3.重启Tomcat服务器。

step4.建立索引>java org.apache.lucene.demo.IndexHTML -create -index [索引数据存放路径] [被索引文件路径](如:D:\lucene\temp\index D:\lucene\temp\docs)step5.打开安装Tomcat的\webapps\luceneweb\configuration.jsp文件,找到String indexLocation = "***",将"***"改为第四步中[索引数据存放路径],保存关闭。

lucene全文检索精华

lucene全文检索精华

lucene全文检索精华lucene全文检索1 概念全文检索(Full-Text Retrieval)是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。

当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程.1.1 lucene全文检索的特性全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。

全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索的特性,我们要知道:1,只处理文本。

2,不处理语义。

3,搜索时英文不区分大小写。

4,结果列表有相关度排序。

下图就是显示“1+1等于几”这个搜索要求对应的结果。

可以看到,是没有“2”这个结果的,结果页面都是出现了这些词的网页 .1.2 全文检索的应用场景我们使用Lucene,主要是做站内搜索,即对一个系统内的资源进行搜索。

如BBS、BLOG中的文章搜索,网上商店中的商品搜索等。

使用Lucene的项目有Eclipse、Jira等。

一般不做互联网中资源的搜索,因为不易获取与管理海量资源(专业搜索方向的公司除外)。

2 第一个lunece程序2.1 准备lucene的开发环境搭建Lucene的开发环境只需要加入Lucene的Jar包,要加入的jar包至少要有: ? lucene-core-4.4.0.jar(核心包)? analysis\\common\\lucene-analyzers-common-4.4.0.jar(分词器) ?highlighter\\lucene-highlighter-4.4.0.jar(高亮) ? \\memory\\lucene-memory-4.4.0.jar(高亮)? queryparser\\ lucene-queryparser-4.4.0.jar (查询解析)2.2 实现建立索引功能(IndexWriter)/*** 使用indexWriter对数据库建立索引.. * @throws IOException */ @Test public void createIndex() throws IOException{//索引存放的位置...Directory directory=FSDirectory.open(new File(\));//lucene当前使用的匹配版本Version matchVersion=Version.LUCENE_44;//分词器,对文本进行分词,抽象类,由子类实现不同的分词方式Analyzer analyzer=new StandardAnalyzer(matchVersion); //索引写入的配置 IndexWriterConfig indexWriterConfig=new//构建用于操作索引的类IndexWriter indexWriter=new IndexWriter(directory,IndexWriterConfig(matchVersion, analyzer);indexWriterConfig);//索引库里面的要遵守一定的结构,(索引结构...) 在索引库当中保存的都是documentDocument doc=new Document(); //索引document里面页游很多的字段... /** * 1:字段的名称 * 2:字段对应的值* 3:该字段在索引库中是否存储 */IndexableField id=new IntField(\, 1, Store.YES);//StringField不会根据分词器去拆分,只有后面的String全包括才能被搜索到IndexableField title=new StringField(\, \培训,传智播客//TextField如果按照默认分词器去拆分,中文则是按照单个中文拆分的专注Java培训10年\, Store.YES);IndexableField content=new TextField(\, \培训的龙头老大,口碑最好的java培训机构,进来看看同学们的呐喊\, Store.YES);doc.add(id);}doc.add(title); doc.add(content);indexWriter.addDocument(doc);indexWriter.close();2.3 实现搜索功能(IndexSearcher)/*** 使用indexSearcher对数据进行搜索 * @throws IOException */ @Testpublic void queryIndex() throws IOException{//索引存放的位置Directory directory=FSDirectory.open(new File(\)); //创建索引读取器IndexReader indexReader=DirectoryReader.open(directory);//通过indexSearcher去检索索引目录...IndexSearcher indexSearcher=new IndexSearcher(indexReader);//我们以后只要根据索引查找,整个过程肯定要分2次..//这是一个搜索条件..,通过定义条件来进行查找...(可以拿到编号,编号都放在了//term 我需要根据哪个字段进行检索,字段对应的值...//Query是抽象类,由子类去实现不同的查询规则Query query=new TermQuery(new Term(\, \));//搜索先搜索索引目录(第一次搜)..不会直接搜索到document(第二次搜) //找到符合query条件的前面N条记录...如果不加条件则会全部查询出来ScoreDoc数组中,遍历数组就获得了编号)TopDocs topDocs=indexSearcher.search(query, 10); System.out.println(\总记录数是:\+topDocs.totalHits);//返回结果的数组(得分文档)ScoreDoc[] scoreDocs=topDocs.scoreDocs; //返回一个击中..for(ScoreDoc scoreDoc:scoreDocs){int docID=scoreDoc.doc; //根据编号去击中对应的文档//lucene的索引库里有很多document,lucene为每个document定义一个编号,唯一标识(docId),是自增长的。

Lucene入门与使用

Lucene入门与使用

中国Lucene入门与使用本文主要面向具体使用,适用于已熟悉java编程的lucene初学者。

1. Lucene的简介1.1 Lucene 历史org.apache.lucene包是纯java语言的全文索引检索工具包。

Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。

目前,lucene广泛用于全文索引/检索的项目中。

lucene也被翻译成C#版本,目前发展为(不过最近好象有流产的消息)。

1.2 Lucene 原理lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。

在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。

因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。

2.Lucene的下载和配置2.1 Lucene的下载lucene在jakarta项目中的发布主页:/lucene/docs/index.html。

以下主要针对windows 用户,其它用户请在上面的地址中查找相关下载。

lucene的.jar包的下载(包括.jar和一个范例demo):/jakarta/lucene/binaries/lucene-1.4-fina l.ziplucene的源代码下载:/mirrors/apache/jakarta/lucene/source/lucene-1 .4-final-src.ziplucene的api地址:/lucene/docs/api/index.html本文使用lucene版本:lucene-1.4-final.jar。

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...这两天加班,不能兼顾博客的更新,请大家见谅。

有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引。

对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的;这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建。

对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况,这势必严重影响用户的体验;比较常见的增量索引的实现是:•设置一个定时器,定时从数据源中读取比现有索引文件中新的内容或是数据源中带有更新标示的数据。

•对数据转换成需要的document并进行索引这样做较以上的那种全删除索引然后重建的好处在于:•数据源查询扫描的数据量小•相应的更新索引的条数也少,减少了大量的IndexWriter的commit和close这些耗时操作以上解决了增量的问题,但是实时性的问题还是存在的:•索引的变更只有在IndexWriter的commit执行之后才可以体现出来那么我们怎样对实时性有个提升呢,大家都知道lucene索引可以以文件索引和内存索引两种方式存在,相较于文件索引,内存索引的执行效率要高于文件索引的构建,因为文件索引是要频繁的IO操作的;结合以上的考虑,我们采用文件索引+内存索引的形式来进行lucene 的增量更新;其实现机制如下:•定时任务扫描数据源的变更•对获得的数据源列表放在内存中•内存中的document达到数量限制的时候,以队列的方式删除内存中的索引,并将之添加到文件索引•查询的时候采用文件+内存索引联合查询的方式以达到NRT效果定时任务调度器java内置了TimerT ask,此类是可以提供定时任务的,但是有一点就是TimerTask的任务是无状态的,我们还需要对任务进行并行的设置;了解到quartz任务调度框架提供了有状态的任务StatefulJob,即在本次调度任务没有执行完毕时,下次任务不会执行;常见的我们启动一个quartz任务的方式如下:[java] view plain copy1.Date runTime = DateBuilder.evenSecondDate(new Date()) ;2.StdSchedulerFactory sf = new StdSchedulerFactory();3.Scheduler scheduler = sf.getScheduler();4.JobDetail job = JobBuilder.newJob(XXX.class).build();5.Trigger trigger = TriggerBuilder.newTrigger().startAt(runTi me).withSchedule(SimpleScheduleBuilder.simpleSchedule().withI ntervalInSeconds(3).repeatForever()).forJob(job).build();6.scheduler.scheduleJob(job, trigger);7.8.scheduler.start();</span>以上我们是设置了每三秒执行一次定时任务,而任务类是XXX 任务类通用方法这里我定义了一个XXX的父类,其定义如下:[java] view plain copy1.package com.chechong.lucene.indexcreasement;2.3.import java.util.List;4.import java.util.TimerTask;5.6.import org.apache.lucene.store.RAMDirectory;7.import org.quartz.Job;8.import org.quartz.StatefulJob;9.10./**有状态的任务:串行执行,即不允许上次执行没有完成即开始本次如果需要并行给接口改为Job即可11.* @author lenovo12.*13.*/14.public abstract class BaseInCreasementIndex implem ents StatefulJob {15./**16.* 内存索引17.*/18.private RAMDirectory ramDirectory;19.public BaseInCreasementIndex() {20.}21.public BaseInCreasementIndex(RAMDirectory ramDire ctory) {22.super();23.this.ramDirectory = ramDirectory;24.}25.26./**更新索引27.* @throws Exception28.*/29.public abstract void updateIndexData() throws Excep tion;30./**消费数据31.* @param list32.*/33.public abstract void consume(List list) throws Excepti on;34.}任务类相关实现,以下方法是获取待添加索引的数据源XXXInCreasementIndex[java] view plain copy1.@Override2.public void execute(JobExecutionContext context) throw s JobExecutionException {3.try {4.XXXInCreasementIndex index = new XXXInCreasementIn dex(Constants.XXX_INDEX_PATH, XXXDao.getInstance(), RamDir ectoryControl.getRAMDireactory());5.index.updateIndexData();6.} catch (Exception e) {7.// TODO Auto-generated catch block8.e.printStackTrace();9.}10.}[java] view plain copy1.@Override2.public void updateIndexData() throws Exception {3.int maxBeanID = SearchUtil.getLastIndexBeanID();4.System.out.println(maxBeanID);5.List<XXX> sources = XXXDao.getListInfoBefore(maxBeanID);、、6.if (sources != null && sources.size() > 0) {7.this.consume(sources);8.}9.}这里,XXX代表我们要获取数据的实体类对象consume方法主要是做两件事:•数据存放到内存索引•判断内存索引数量,超出限制的话以队列方式取出超出的数量,并将之存放到文件索引[java] view plain copy1.@Override2.public void consume(List list) throws Exception {3.IndexWriter writer = RamDirectoryControl.getRAMIndex Writer();4.RamDirectoryControl.consume(writer,list);5.}上边我们将内存索引和队列的实现放在了RamDirectoryControl 中内存索引控制器首先我们对内存索引的IndexWriter进行初始化,在初始化的时候需要注意先执行一次commit,否则会提示no segments的异常[java] view plain copy1.private static IndexWriter ramIndexWriter;2.private static RAMDirectory directory;3.static{4.directory = new RAMDirectory();5.try {6.ramIndexWriter = getRAMIndexWriter();7.} catch (Exception e) {8.// TODO Auto-generated catch block9.e.printStackTrace();10.}11.}12.public static RAMDirectory getRAMDireactory(){13.return directory;14.}15.public static IndexSearcher getIndexSearcher() throw s IOException{16.IndexReader reader = null;17.IndexSearcher searcher = null;18.try {19.reader = DirectoryReader.open(directory);20.} catch (IOException e) {21. e.printStackTrace();22.}23.searcher = new IndexSearcher(reader);24.return searcher;25.}26./**单例模式获取ramIndexWriter27.* @return28.* @throws Exception29.*/30.public static IndexWriter getRAMIndexWriter() throw s Exception{31.if(ramIndexWriter == null){32.synchronized (IndexWriter.class) {33.Analyzer analyzer = new IKAnalyzer();34.IndexWriterConfig iwConfig = new IndexWriterConfig (analyzer);35.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);36.try {37.ramIndexWriter = new IndexWriter(directory, iwConfig);mit();39.ramIndexWriter.close();40.iwConfig = new IndexWriterConfig(analyzer);41.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);42.ramIndexWriter = new IndexWriter(directory, iwConfig);43.} catch (IOException e) {44.// TODO Auto-generated catch block45. e.printStackTrace();46.}47.}48.}49.50.return ramIndexWriter;51.}定义一个获取内存索引中数据条数的方法[java] view plain copy1./**根据查询器、查询条件、每页数、排序条件进行查询2.* @param query 查询条件3.* @param first 起始值4.* @param max 最大值5.* @param sort 排序条件6.* @return7.*/8.public static TopDocs getScoreDocsByPerPageAndSortFi eld(IndexSearcher searcher,Query query, int first,int max, Sort s ort){9.try {10.if(query == null){11.System.out.println(" Query is null return null ");12.return null;13.}14.TopFieldCollector collector = null;15.if(sort != null){16.collector = TopFieldCollector.create(sort, first+max, fal se, false, false);17.}else{18.SortField[] sortField = new SortField[1];19.sortField[0] = new SortField("createTime",SortField.Ty pe.STRING,true);20.Sort defaultSort = new Sort(sortField);21.collector = TopFieldCollector.create(defaultSort,first+ max, false, false, false);22.}23.searcher.search(query, collector);24.return collector.topDocs(first, max);25.} catch (IOException e) {26.// TODO Auto-generated catch block27.}28.return null;29.}此方法返回结果为T opDocs,我们根据TopDocs的totalHits来获取内存索引中的数据条数,以此来鉴别内存占用,防止内存溢出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档