page类,
分页使用到的,分页无非就是使用到类 select * from table limit FROM,TO
在数据库中做分页查询的时候,我们要想知道获取数据的起始位置和结束位置,就要知道每页显示的数据个数,
我们可以根据数据总个数和每页显示的数据个数算出来总页数。
page类
1 | public class PageBean<T>(){ |
getter()和setter()方法
}
1 |
|
Controller层
1 |
|
Service的书写
SearchRequest包含了From和pageSize
1 | public List<T> getRecord(SearchRequest searchRequest, PageBean<ResultClassName> pageBean) { |
SQL的写法
1 | <select id="getRepairRecord" resultType="ResultClassName" |
java8的lambda表达式:
前世-匿名类
举一个匿名类的例子:
Comparator接口:
1 | public interface Comparator<T> { |
使用匿名类创建排序的比较方法:注意new Comparator
1 | Collections.sort(words, new Comparator<String>(){ |
匿名类适用于需要函数对象的经典面向对象设计模式,特别是策略模式,上面的匿名类是排序字符串的具体策略。然而,匿名类确实过于冗长。
起到的作用是,新new了一个接口,接口一个方法为compare,有两个参数s1,s2,
为什么sort里面要有一个Comparator接口,这么麻烦
sort点进去有binarysort,不管Objcet实际是什么类型的,都可以使用接口中定义的方法。
可能会有个疑问,为什么不在Object这个超类中定义这个方法然后子类重写,而是要用实现接口呢。这个嘛,是因为大部分用不着这个功能,写上去就会用浪费,我们就用接口来弥补,你要你就实现接口。
Lambda表达式的今生
在 Java 8 中,语言形式化了这样的概念,即使用单个抽象方法的接口是特别的,应该得到特别的对待。即一个接口只有一个方法。
这些接口现在称为函数式接口,并且该语言允许你使用lambda 表达式或简称 lambda 来创建这些接口的实例。
Lambdas 在功能上与匿名类相似,但更为简洁。下面的代码使用 lambdas 替换上面的匿名类。清晰明了
1 | Collections.sort(words,(s1,s2)-> |
1 | new Comparator<String>(){ |
等价于
1 | (s1,s2)->Integer.compare(s1.length(),s2.length()) |
右边的东西形成了一个函数,这个函数需要两个参数,s1,s2.
1 | customSchemaRepository.findAll((root,criteriaQuery,criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)) |
Lambda表达式的语法非常简洁,但是使用时有几个问题需要特别注意:
- 使用Lambda表达式必须具有接口,且要求接口中有且仅有一个抽象方法。
- 使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
Lambda标准形式
(参数类型 参数名称) ‐> { 代码语句 }
说明:
- 小括号内:没有参数就留空(),多个参数就用逗号分隔。
- -> 是新引入的语法格式,代表指向动作。
- 大括号内的语法与传统方法体要求基本一致。
Lambda的省略:凡是可以根据上下文推导得知的信息,都可以省略
在Lambda表达式标准形式的基础上:
- 小括号内参数的类型可以省略;
- 如果小括号内只有一个参数,则小括号可以省略;
- 如果大括号内只有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
综上所述,从 Java 8 开始,lambda 是迄今为止表示小函数对象的最佳方式。除非必须创建非函数式接口类型的实例,否则不要使用匿名类作为函数对象。
备注:有且仅有一个抽象方法的接口,称为“函数式接口”。
内连接(INNER JOIN)实例
LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。
1 | SELECT column_name(s) FROM table_name WHERE column_name LIKE pattern |
现在,我们希望从上面的 “Persons” 表中选取居住在以 “N” 开始的城市里的人:
我们可以使用下面的 SELECT 语句:
1 | SELECT * FROM Persons |
TF-IDF(term frequency–inverse document frequency)
是一种用于信息检索与数据挖掘的常用加权技术。
TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。
ES(elasticsearch)搜索引擎
什么是搜索?
根据一个搜索词,检索出所有包含该词的数据
例如:用户在搜索框输入一个词,客户端软件发送一个请求到后台,后台通过sql语句从数据库中找出相关条目(数据库会一条一条的对比),这就是一个最简单搜索原型
普通搜索面临的问题
1, 当数据量很大时,假如500G, 效率低。从用户角度,从点击搜索按钮到看到搜索结果可能要很长时间,1小时?2小时?用户疯掉
2, 当数据量达到1T,一台电脑已经放不下了,这时候就需要多台,这就是分布式。这时候数据就在不同的服务器了,一个客户端不可能去请求每台机器,所以就需要一个管理员角色,负责把客户端请求分发到每台机器,同时汇总结果返回给客户端
普通搜索速度简单优化(倒排索引)
数据库每个条目的名称进行分词,形成一个key为词,value为条目id的数据表。同时对用户输入的搜索词进行分词,检索出每个词在数据库中的id,求个交集,然后把这些id查不出返回就行了。
输入 复仇者联盟, 经过分词后变成
[复仇者,联盟]
倒排索引表也已经建好了,可能长这样
复仇者 4,5,6,11 数字为文档编号
联盟 5,9,11
倒排索引
需要根据属性的值来查找记录,这种索引表中的每一项都包括一个[属性值, 具有该属性值的各个记录的地址]。
由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。
带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。
倒排列表用来记录有哪些文档包含了某个单词,一般在文档集合里会有很多文档 包含某个单词,每个文档会记录文档编号(DocID),单词在这个文档中出现的次数(TF)及单词在文档中哪些位置出现过等信息.这样与一个文档相关的信息被称做倒排索引项(Posting)。并不存储倒排索引项中的实际文档编号,而是代之以文档编号差值(D-Gap),原始的 3个文档编号分别是187、196和199,通过编号差值计算,在实际存储的时候就转化成了:187、9、3。
之所以要对文档编号进行差值计算,主要原因是为了更好地对数据进行压缩,原始文档编号一般都是大数值,通过差值计算,就有效地将大数值转换为了小数值,而这有助于增加数据的压缩率。
索引构建方法
简单法
索引的构建相当于从正排表到倒排表的建立过程。当我们分析完网页时 ,得到的是以网页为主码的索引表。
流程描述如下:
1)将文档分析成单词term标记,
2)使用hash去重单词term
3)对单词生成倒排列表
倒排列表就是文档编号DocID,没有包含其他的信息(如词频,单词位置等),这就是简单的索引。
这个简单索引功能可以用于小数据,例如索引几千个文档。然而它有两点限制:
1)需要有足够的内存来存储倒排表,对于搜索引擎来说, 都是G级别数据,特别是当规模不断扩大时 ,我们根本不可能提供这么多的内存。
2)算法是顺序执行,不便于并行处理。
合并法
归并法,即每次将内存中数据写入磁盘时,包括词典在内的所有中间结果信息都被写入磁盘,这样内存所有内容都可以被清空,后续建立索引可以使用全部的定额内存。
如图4归并示意图:
合并流程:
1)页面分析,生成临时倒排数据索引A,B,当临时倒排数据索引A,B占满内存后,将内存索引A,B写入临时文件生成临时倒排文件,
\2) 对生成的多个临时倒排文件 ,执行多路归并 ,输出得到最终的倒排文件 ( inverted file)。
索引创建过程中的页面分析 ,特别是中文分词为主要时间开销。算法的第二步相对很快。这样创建算法的优化集中在中文分词效率上。
假设只存在正向索引(forward index),那么就需要扫描索引库中的所有文档,找出所有包含关键词“华为手机”的文档,再根据打分模型进行打分,排出名次后呈现给用户。
得到正向索引的结构如下:
“文档1”的ID > 单词1:出现次数,出现位置列表;单词2:出现次数,出现位置列表;…………。
“文档2”的ID > 此文档出现的关键词列表。
[文档ID,关键词]
因为互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。
就是每个关键词都要去扫描库中的所有文档
所以,搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射
[关键词,文件ID]
从词的关键字,去找文档。