Lucene中的Field域、索引维护、搜索、相关度排序和中文分词器讲解

news2024/11/23 7:46:05

Field域

Field属性

Field是文档中的域,包括Field名Field值两部分,一个文档可以包括多个Field,Document只是Field的一个承载体,Field值即为要索引的内容,也是要搜索的内容。

  • 是否分词(tokenized)

是:作分词处理,即将Field值进行分词,分词的目的是为了索引
比如:商品名称、商品简介等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分词后将语汇单元索引。

否:不作分词处理
比如:商品id、订单号、身份证号等

  • 是否索引(indexed)

是:进行索引。将Field分词后的词或整个Field值进行索引,索引的目的是为了搜索
比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。

否:不索引。该域的内容无法搜索到
比如:商品id、文件路径、图片路径等,不用作为查询条件的不用索引。

  • 是否存储(stored)

是:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取。
比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。

否:不存储Field值,不存储的Field无法通过Document获取
比如:商品简介,内容较大不用存储。如果要向用户展示商品简介可以从系统的关系数据库中获取商品简介。

Field常用类型

下边列出了开发中常用的Filed类型,注意Field的属性,根据需求选择:

Field类数据类型Analyzed是否分词Indexed是否索引Stored是否存储说明
StringField(FieldName, FieldValue,Store.YES))字符串NYY或N这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等)是否存储在文档中用Store.YES或Store.NO决定
LongField(FieldName, FieldValue,Store.YES)Long型YYY或N这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格) 是否存储在文档中用Store.YES或Store.NO决定
StoredField(FieldName, FieldValue)重载方法,支持多种类型NNY这个Field用来构建不同类型Field不分析,不索引,但要Field存储在文档中
TextField(FieldName, FieldValue, Store.NO) 或 TextField(FieldName, reader)字符串或流YYY或N如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

Field代码修改如下

图书id:
是否分词:不用分词,因为不会根据商品id来搜索商品
是否索引:不索引,因为不需要根据图书ID进行搜索
是否存储:要存储,因为查询结果页面需要使用id这个值。

图书名称:
是否分词:要分词,因为要将图书的名称内容分词索引,根据关键搜索图书名称抽取的词。
是否索引:要索引。
是否存储:要存储。

图书价格:
是否分词:要分词,lucene对数字型的值只要有搜索需求的都要分词和索引,因为lucene对数字型的内容要特殊分词处理,本例子可能要根据价格范围搜索,需要分词和索引。
是否索引:要索引
是否存储:要存储

图书图片地址:
是否分词:不分词
是否索引:不索引
是否存储:要存储

图书描述:
是否分词:要分词
是否索引:要索引
是否存储:因为图书描述内容量大,不在查询结果页面直接显示,不存储。

不存储是来不在lucene的索引文件中记录,节省lucene的索引文件空间,如果要在详情页面显示描述,思路:
从lucene中取出图书的id,根据图书的id查询关系数据库中book表得到描述信息。

代码案例:

        	// 图书ID
			// 参数:域名、域中存储的内容、是否存储
			// 不分词、索引、要存储
			// Field id = new TextField("id", book.getId().toString(),
			// Store.YES);
			Field id = new StoredField("id", book.getId().toString(), Store.YES);
			// 图书名称
			// 分词、索引、存储
			Field bookname = new TextField("bookname", book.getName(),
					Store.YES);
			// 图书价格
			// 分词、索引、存储
			Field price = new FloatField("price", book.getPrice(), Store.YES);
			// 图书图片
			// 不分词、不索引、要存储
			Field pic = new StoredField("pic", book.getPic());
			// 图书描述
			// 分词、索引、不存储
			Field description = new TextField("description",
					book.getDescription(), Store.NO);

索引维护

需求

管理人员通过电商系统更改图书信息,这时更新的是数据库,如果使用lucene搜索图书信息需要在数据库表book信息变化时及时更新lucene索引库。

添加索引

调用indexWriter.addDocument(doc)添加索引。
参考上篇博客Lucene和Solr和Elasticsearch区别,全文检索引擎工具包Lucene索引流程和搜索流程实操的创建索引。

删除索引

删除指定索引

根据Term项删除索引,满足条件的将全部删除。
代码实现:

   /**
     * 删除索引
     * @throws Exception
     */
    @Test
    public void deleteIndex() throws Exception {
        // 1、指定索引库目录
        Path path = Paths.get("D:\\usr\\lucene\\");
        Directory directory = FSDirectory.open(path);
        // 2、创建IndexWriterConfig
        IndexWriterConfig cfg = new IndexWriterConfig(new StandardAnalyzer());
        // 3、 创建IndexWriter
        IndexWriter writer = new IndexWriter(directory, cfg);
        // 4、通过IndexWriter来删除索引
        // b)、删除指定索引
        writer.deleteDocuments(new Term("filename", "apache"));
        // 5、关闭IndexWriter
        writer.close();
    }

删除全部索引(慎用)

将索引目录的索引信息全部删除,直接彻底删除,无法恢复。慎用!!!
代码实现:

    /**
     * 删除全部索引
     * @throws Exception
     */
    @Test
    public void deleteAllIndex() throws Exception {
        // 1、指定索引库目录
        Path path = Paths.get("D:\\usr\\lucene\\");
        Directory directory = FSDirectory.open(path);
        // 2、创建IndexWriterConfig
        IndexWriterConfig cfg = new IndexWriterConfig(new StandardAnalyzer());
        // 3、 创建IndexWriter
        IndexWriter writer = new IndexWriter(directory, cfg);
        // 4、通过IndexWriter来删除索引
        // a)、删除全部索引
        writer.deleteAll();
        // 5、关闭IndexWriter
        writer.close();
    }

建议参照关系数据库基于主键删除方式,所以在创建索引时需要创建一个主键Field,删除时根据此主键Field删除。
索引删除后将放在Lucene的回收站中,Lucene3.X版本可以恢复删除的文档,3.X之后无法恢复。

修改索引

更新索引是先删除再添加,建议对更新需求采用此方法并且要保证对已存在的索引执行更新,可以先查询出来,确定更新记录存在执行更新操作。
代码实现:

    /**
     * 修改索引
     * @throws Exception
     */
    @Test
    public void updateIndex() throws Exception {
        // 1、指定索引库目录
        Path path = Paths.get("D:\\usr\\lucene\\");
        Directory directory = FSDirectory.open(path);
        // 2、创建IndexWriterConfig
        IndexWriterConfig cfg = new IndexWriterConfig(new StandardAnalyzer());
        // 3、 创建IndexWriter
        IndexWriter writer = new IndexWriter(directory, cfg);
        // 4、通过IndexWriter来修改索引
        // a)、创建修改后的文档对象
        Document document = new Document();

        // 文件名称
        Field filenameField = new StringField("filename", "updateIndex", Field.Store.YES);
        document.add(filenameField);

        // 修改指定索引为新的索引
        writer.updateDocument(new Term("filename", "apache"), document);

        // 5、关闭IndexWriter
        writer.close();
    }

搜索

创建查询的两种方法

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法。类似关系数据库Sql语法一样,Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。
可通过两种方法创建查询对象:

  1. 使用Lucene提供Query子类

Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。
如下代码:

Query query = new TermQuery(new Term("name", "lucene"));
  1. 使用QueryParse解析查询表达式

QueryParser会将用户输入的查询表达式解析成Query对象实例。
如下代码:

QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
Query query = queryParser.parse("name:lucene");

通过Query子类搜索

TermQuery

TermQuery项查询,TermQuery不使用分析器,搜索关键词作为整体来匹配Field域中的词进行查询,比如订单号、分类ID号等。
代码案例:

    /**
     * 搜索
     * @param query
     */
    private void doSearch(Query query) {
        IndexReader reader = null;
        try {
            // a) 指定索引库目录
            Path path = Paths.get("D:\\usr\\lucene\\");
            Directory directory = FSDirectory.open(path);
            // b) 创建IndexReader对象
            reader = DirectoryReader.open(directory);
            // c) 创建IndexSearcher对象
            IndexSearcher searcher = new IndexSearcher(reader);
            // d) 通过IndexSearcher对象执行查询索引库,返回TopDocs对象
            // 第一个参数:查询对象
            // 第二个参数:最大的n条记录
            TopDocs topDocs = searcher.search(query, 10);
            // e) 提取TopDocs对象中的文档ID,如何找出对应的文档
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            System.out.println("总共查询出的结果总数为:" + topDocs.totalHits);
            Document doc;
            for (ScoreDoc scoreDoc : scoreDocs) {
                // 文档对象ID
                int docId = scoreDoc.doc;
                doc = searcher.doc(docId);
                // f) 输出文档内容
                System.out.println("商品ID:" + doc.get("id"));
                System.out.println("商品名称:" + doc.get("name"));
                System.out.println("商品价格:" + doc.get("price"));
                System.out.println("商品图片地址:" + doc.get("pic"));
                System.out.println("==========================");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * TermQuery搜索
     * @throws Exception
     */
    @Test
    public void testTermQuery() throws Exception {
        // 1、 创建查询(Query对象)
        Query query = new TermQuery(new Term("description", "mybatis"));
        // 2、 执行搜索
        doSearch(query);
    }

xxxRangeQuery

FloatPoint.newRangeQuery,指定数字范围查询.
代码案例:

    @Test
    public void testRangeQuery() throws Exception {
        // 创建查询
        // 第一个参数:域名
        // 第二个参数:最小值
        // 第三个参数:最大值
        Query query = FloatPoint.newRangeQuery("price", 0, 500);
        // 2、 执行搜索
        doSearch(query);
    }

BooleanQuery

BooleanQuery,布尔查询,实现组合条件查询。

@Test
	public void booleanQuery() throws Exception {
		BooleanQuery query = new BooleanQuery();
		Query query1 = new TermQuery(new Term("id", "3"));
		Query query2 = NumericRangeQuery.newFloatRange("price", 10f, 200f,
				true, true);

		//MUST:查询条件必须满足,相当于AND
		//SHOULD:查询条件可选,相当于OR
		//MUST_NOT:查询条件不能满足,相当于NOT非
		query.add(query1, Occur.MUST);
		query.add(query2, Occur.SHOULD);
		
		System.out.println(query);

		search(query);
	}

组合关系代表的意思如下:

  1. MUST和MUST表示“与”的关系,即“并集”。
  2. MUST和MUST_NOT前者包含后者不包含。
  3. MUST_NOT和MUST_NOT没意义
  4. SHOULD与MUST表示MUST,SHOULD失去意义;
  5. SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
  6. SHOULD与SHOULD表示“或”的概念。

通过QueryParser搜索

通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过**System.out.println(query);**查询。

QueryParser

代码实现

    @Test
    public void testQueryParser() throws Exception {
        // 创建QueryParser
        // 第一个参数:默认域名
        // 第二个参数:分词器
        QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
        // 指定查询语法 ,如果不指定域,就搜索默认的域
        Query query = queryParser.parse("lucene");
        System.out.println(query);
        // 2、 执行搜索
        doSearch(query);

    }

查询语法

  1. 基础的查询语法,关键词查询:

域名+“:”+搜索的关键字
例如:content:java

  1. 范围查询

域名+“:”+[最小值 TO 最大值]
例如:size:[1 TO 1000]
注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。

  1. 组合条件查询
Occur.MUST 查询条件必须满足,相当于and(加号)
Occur.SHOULD 查询条件可选,相当于or空(不用符号)
Occur.MUST_NOT 查询条件不能满足,相当于not非-(减号)
  1. +条件1 +条件2:两个条件之间是并且的关系and

例如:+filename:apache +content:apache

  1. +条件1 条件2:必须满足第一个条件,忽略第二个条件

例如:+filename:apache content:apache

  1. 条件1 条件2:两个条件满足其一即可。

例如:filename:apache content:apache

  1. -条件1 条件2:必须不满足条件1,要满足条件2

例如:-filename:apache content:apache

第二种写法:
条件1 AND 条件2
条件1 OR 条件2
条件1 NOT 条件2

MultiFieldQueryParser

通过MuliFieldQueryParse对多个域查询。

    @Test
    public void testMultiFieldQueryParser() throws Exception {
        // 可以指定默认搜索的域是多个
        String[] fields = { "name", "description" };
        // 创建一个MulitFiledQueryParser对象
        QueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
        // 指定查询语法 ,如果不指定域,就搜索默认的域
        Query query = parser.parse("lucene");
        // 2、 执行搜索
        doSearch(query);
    }

TopDocs

Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:

方法或属性说明
totalHits匹配搜索条件的总记录数
scoreDocs顶部匹配记录

注意:
Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)
TopDocs.totalHits:是匹配索引库中所有记录的数量
TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n

相关度排序

什么是相关度排序

相关度排序是查询结果按照与查询关键字的相关性进行排序,越相关的越靠前。比如搜索“Lucene”关键字,与该关键字最相关的文章应该排在前边。

相关度打分

Lucene对查询关键字和索引文档的相关度进行打分,得分高的就排在前边。如何打分呢?Lucene是在用户进行检索时实时根据搜索的关键字计算出来的,分两步:

  1. 计算出词(Term)的权重
  2. 根据词的权重值,计算文档相关度得分。

什么是词的权重?
通过索引部分的学习,明确索引的最小单位是一个Term(索引词典中的一个词),搜索也是要从Term中搜索,再根据Term找到文档,Term对文档的重要性称为权重,影响Term权重有两个因素:

  • Term Frequency (tf):

**指此Term在此文档中出现了多少次。tf 越大说明越重要。 **
词(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“Lucene”这个词,在文档中出现的次数很多,说明该文档主要就是讲Lucene技术的。

  • Document Frequency (df):

**指有多少文档包含次Term。df 越大说明越不重要。 **
比如,在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。

设置boost值影响相关度排序

boost是一个加权值(默认加权值为1.0f),它可以影响权重的计算。

  • 在索引时对某个文档中的field设置加权值高,在搜索时匹配到这个文档就可能排在前边。
  • 在搜索时对某个域进行加权,在进行组合域查询时,匹配到加权值高的域最后计算的相关度得分就高。

设置boost是给域(field)或者Document设置的。

在创建索引时设置

如果希望某些文档更重要,当此文档中包含所要查询的词则应该得分较高,这样相关度排序可以排在前边,可以在创建索引时设定文档中某些域(Field)的boost值来实现,如果不进行设定,则Field Boost默认为1.0f。一旦设定,除非删除此文档,否则无法改变

中文分词器

什么是中文分词器

学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开。而中文则以字为单位,字又组成词,字和词再组成句子。所以对于英文,我们可以简单以空格判断某个字符串是否为一个单词,比如I love China,love 和 China很容易被程序区分开来;但中文“我爱中国”就不一样了,电脑不知道“中国”是一个词语还是“爱中”是一个词语。把中文的句子切分成有意义的词,就是中文分词,也称切词。我爱中国,分词的结果是:我爱中国。

Lucene自带的中文分词器

  • StandardAnalyzer

单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
效果:“我”、“爱”、“中”、“国”。

  • CJKAnalyzer

二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。
上边两个分词器无法满足需求。

第三方中文分词器

  • paoding: 庖丁解牛最新版在 https://code.google.com/archive/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代码在 2008-06-03,在svn中最新也是2010年提交,已经过时,不予考虑。
  • mmseg4j:最新版已从 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代码是2014年6月,从09年~14年一共有:18个版本,也就是一年几乎有3个大小版本,有较大的活跃度,用了mmseg算法。
  • IK-analyzer:最新版在https://code.google.com/archive/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。GitHub地址:https://github.com/wks/ik-analyzer
  • ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags仅有1.1版本,从2012年到2014年更新了大小6次,但是作者本人在2014年10月10日说明:“可能我以后没有精力来维护ansj_seg了”,现在由”nlp_china”管理。2014年11月有更新。并未说明是否支持Lucene,是一个由CRF(条件随机场)算法所做的分词算法。
  • imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/ ,最新更新也在2009年5月,下载源码,不支持Lucene 4.10 。是利用HMM(隐马尔科夫链)算法。
  • Jcseg:最新版本在https://gitee.com/lionsoul/jcseg,支持Lucene 4.10,作者有较高的活跃度。利用mmseg算法。

使用中文分词器IKAnalyzer

IKAnalyzer继承Lucene的Analyzer抽象类,使用IKAnalyzer和Lucene自带的分析器方法一样,将Analyzer测试代码改为IKAnalyzer测试中文分词效果。
如果使用中文分词器ik-analyzer,就在索引和搜索程序中使用一致的分词器ik-analyzer。

添加jar包

IKAnalyzer是一个java中文分词包,并没有maven坐标,因此在使用IKAnalyzer需要手动将它添加到maven仓库中。

修改分词器代码

// 创建中文分词器
Analyzer analyzer = new IKAnalyzer();

扩展中文词库

从ikanalyzer包中拷贝配置文件到classpath下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  

  <comment>IK Analyzer 扩展配置</comment>
  <!-- 用户可以在这里配置自己的扩展字典 -->
  <entry key="ext_dict">dicdata/mydict.dic</entry> 
  <!-- 用户可以在这里配置自己的扩展停用词字典    -->
  <entry key="ext_stopwords">dicdata/ext_stopword.dic</entry> 

</properties>

如果想配置扩展词和停用词,就创建扩展词的文件和停用词的文件,文件的编码要是utf-8。
注意:不要用记事本保存扩展词文件和停用词文件,那样的话,格式中是含有bom的
添加扩展词文件:ext.dic,内容如下:

共饮一杯无

使用luke测试中文分词

在这里插入图片描述

使用Luke测试第三方分词器分词效果,需通过java.ext.dirs加载jar包:
可简单的将第三方分词器和lukeall放在一块儿,cmd下运行:
image.png

java -Djava.ext.dirs=. -jar lukeall-4.10.3.jar

在这里插入图片描述

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

事实证明,国产BI软件的财务数据分析性价比极高!

国产BI软件做财务数据分析的性价比极高&#xff0c;主要得益于两个因素&#xff0c;一个是国产BI软件按功能模块购买&#xff0c;大幅度降低BI大数据分析平台的使用成本&#xff1b;另一个则是国产BI软件已打磨出标准化、系统化的财务数据分析方案&#xff0c;低成本、低风险、…

Blender基础技巧小结

官网下载 https://www.blender.org/download/lts/2-83/ 我下载的版本&#xff1a;LTS Release 2.83.20 Windows – Portable Ogre导出插件 https://github.com/OGRECave/blender2ogre 安装插件 将blender2ogre\io_ogre复制到&#xff1a;blender-2.83.20-windows-x64\2.8…

论文阅读-17-Deep Long-Tailed Learning: A Survey---3.1Class Re-balancing

文章目录 1. Re-sampling1.1 Class-balanced re-sampling(1) Decoupling① 网络架构② Sampling策略③ Classifier的学习策略 (2) SimCal① 比较 (3) DCL(4) Balanced meta-softmax(5) FASA(6) LOCE(7) VideoLT 1.2 Scheme-oriented sampling(1) LMLE(2) PRS(3) BBN(4) LTML(5)…

技术赋能光伏组件检测“大尺寸” “高精度”,维视智造SNEC亮点抢先看!

2023.5.24-5.26 全球最具影响力的 国际化、专业化、规模化光伏盛会 第十六届&#xff08;2023&#xff09; SNEC光伏大会暨(上海)展览会 即将开展 维视智造深耕机器视觉行业20年 解决方案落地众多光伏头部企业 如今作为光伏组件视觉检测系统行业领先者 此次展会维视将…

(文章复现)《高比例清洁能源接入下计及需求响应的配电网重构》(含matlab代码)

1.引言 配电网重构作为配电网优化运行的手段之一&#xff0c;通过改变配电网的拓扑结构&#xff0c;以达到降低网损、改善电压分布、提升系统的可靠性与经济性等目的。近年来&#xff0c;随着全球能源消耗快速增长以及环境的日趋恶化&#xff0c;清洁能源飞速发展&#xff0c;分…

从【创作者】转变为【博客专家】-- 内含详细申请过程

从【创作者】转变为【博客专家】 0、引言1、创作身份认证1.1 起因1.2 违背祖宗的决定1.3 认证创作身份1.3.0 好处1.3.1 条件1.3.2 认证信息1.3.3 后台审核 2、博客专家认证2.1 好处2.2 条件2.3 认证信息2.4 后台审核2.5 实体证书 3、 反思与总结 ⚠申明&#xff1a; 未经许可&a…

哪个年龄段人群喜欢养宠物?18-25岁占比最高,达31%

上一期&#xff0c;我们通过可视化互动平台分析了萌宠经济下宠物食品的发展现状&#xff0c;这一期我们接着来分析一下&#xff0c;在萌宠经济下&#xff0c;我国宠物医疗产业的市场情况。 由于现在很多家庭都喜欢饲养宠物&#xff0c;宠物数量的快速增长从而拉动了宠物经济的…

晶飞FLA5000光谱仪.FlaSpec文件数据解析

引言 首先说明下晶飞上位机软件存在的问题&#xff0c;实验所采用的FLA5000型号光谱仪&#xff0c;光谱波段从280-970nm&#xff0c;FWHM值为2.4nm。 1、上位机软件中的光谱数据复制功能基本是废的&#xff0c;最多只能到599.9nm&#xff0c;后面的数据全部消失。 2、上位机软…

NOSQL和REDIS配置与优化

关系数据库与非关系型数据库 ●关系型数据库&#xff1a; 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上&#xff0c;一般面向于记录。 SQL 语句&#xff08;标准数据查询语言&#xff09;就是一种基于关系型数据库…

在外远程访问公司局域网用友畅捷通T财务软件 - 远程办公

文章目录 前言1.本地访问简介2. cpolar内网穿透3. 公网远程访问4. 固定公网地址 前言 用友畅捷通T适用于异地多组织、多机构对企业财务汇总的管理需求&#xff1b;全面支持企业对远程仓库、异地办事处的管理需求&#xff1b;全面满足企业财务业务一体化管理需求。企业一般将其…

ML@基础概念@模型评估和选择理论基础

refs 参考经典机器学习资料西瓜书 主要符号 x x x:标量 x \boldsymbol{x} x:向量(注意是 x x x的粗体形式) x \mathbf{x} x:变量集(正粗体) A \mathbf{A} A:矩阵(正粗体) I \mathbf{I} I:单位阵(正粗体) χ \chi χ:样本空间或状态空间 D \mathcal{D} D:概率分布…

【fly-iot飞凡物联】(5):开源项目Apache IoTDB,开源项目学习,原来还有这样的项目,关于IOT的几个开源项目汇总下

目录 前言1&#xff0c;关于&#xff1a;开源项目Apache IoTDB2&#xff0c;还有个admin后台3&#xff0c;thinglinks项目4&#xff0c;thingsboard-ui-vue项目5&#xff0c;apache pulsar项目6&#xff0c;ActorCloud项目 前言 本文的原文连接是: https://blog.csdn.net/freew…

MySQL多表查询操作

文章目录 前言内连接表别名 外连接左外连接右外连接全外连接 总结 前言 JOIN 表示连接&#xff0c;inner表示内连接&#xff0c;outer表示外连接&#xff0c;缺省情况是内连接。 ON后面接<连接条件> 内连接 默认的表数据连接是内连接&#xff0c;只会查询出满足连接条…

【C++进阶】继承详解

文章目录 前言一、继承的概念及定义1.概念2.继承定义定义格式继承关系和访问限定继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员七、复杂的菱形继承及菱形虚拟继承1.单继承与多继承2.菱…

【Lychee图床】本地电脑搭建私人图床,公网远程访问

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 转发自CSDN风浪越大%鱼越贵的文章&#xff1a;Lychee图床 - 本地配置属于自己的相册管理系统并远…

快速入手光学字符识别控件Aspose.OCR!如何从PDF中提取文本

Aspose.OCR是一款字符识别组件&#xff0c;它使得开发人员可以添加OCR功能到他们的ASP.NET Web应用程序、web服务和windows应用程序中。它提供了一个简单的类集用于控制字符识别。Aspose.OCR目的是为那些需要在他们自己的应用程序中使用图像&#xff08;BMP和TIFF&#xff09;的…

软件设计师计算机系统知识点笔记大总结

数据寄存器是一个中转站 指令寄存器 ir 保存暂存指令&#xff08;操作码加地址吗等于指令&#xff09; 地址寄存器 保存当前cpu所访问的内存单元地址 程序计数器 保存的是下一条指令的地址 状态寄存器 标志运算的结果 类似 0&#xff08;&#xff09;状态寄存器是运算器中的部件…

Ansible Automation Platform - 用 API 访问 Ansible Automation Platform

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在支持 Ansible Automation Platform 2.3 的环境中验证 文章目录 AAP 的 API 索引Host 主机列表 API通过 API 操作 Ansible Automation Platform 说明&#xff1a;以下命令中 mycontroller-aap.apps-crc.t…

论文阅读-17-Deep Long-Tailed Learning: A Survey---3.3 Module Improvement

文章目录 1. Representation Learning1.1 Metric learning(1) large margin local embedding LMLE①##### ②##### ③ (2) Range loss(3) CRL(4) KCL(5) Hybrid(6) PaCo(7) DRO-LT 1.2 Sequential training(1) HFL(2) Unequal-training 1.3 Prototype learning(1) OLTR(2) IEM …

PPT背景图片怎么设置?4个详细教程在这!

案例&#xff1a;PPT背景图片怎么设置&#xff1f; 【因为论文答辩&#xff0c;最近需要制作PPT&#xff0c;昨晚之后感觉有点单调&#xff0c;我想设置一个背景图片&#xff0c;让我的PPT看起来更有风格&#xff0c;请问大家是怎么设置PPT背景图片的呢&#xff1f;】 PPT背景…