项目csmall-finish项目中
node文件夹下共享了ES文档,命令都在里面,可以测试
所有的代码都在"ES文档"中, 笔记略
下面我们要学习使用java代码来操作ES
原生状态下,我们使用JDBC连接数据库,因为代码过于繁琐,所以改为使用Mybatis框架
在ES的原生状态下,我们java代码需要使用socket访问ES,但是也是过于繁琐,我们可以使用SpringData框架简化
Spring Data是Spring提供的一套连接各种第三方数据源的框架集
我们需要使用的是其中连接ES的Spring Data Elasticseatrch
官方网站:Spring Data

官网中列出了SpringData支持连接操作的数据源列表
下面我们就按照SpringDataElasticsearch的步骤对ES进行操作
就使用我们之前创建的search模块来操作ES
pom文件添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>search</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring data elasticsearch 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 为了方便测试添加测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
application.properties添加配置
# 设置ES所在的ip地址端口号
spring.elasticsearch.rest.uris=http://localhost:9200
# 设置日志门槛,用于显示ES的运行信息
logging.level.cn.tedu.search=debug
# SpringDataElasticsearch底层有一个专门输出运行状态的类,也要设置
logging.level.org.elasticsearch.client.RestClient=debug
和数据库一样
我们操作ES时也需要一个类似实体类的数据类,作为操作ES的数据载体
search项目创建entity包
在包中创建Item(商品)类
@Data
@Accessors(chain = true) // 支持链式set赋值功能
@AllArgsConstructor // 自动生成当前类的全参构造
@NoArgsConstructor // 自动生成当前类的无参构造
// @Document是SpringDataES框架标记实体类的注解
// indexName指定的是索引名称,运行时items索引不存在,SpringDataES会自动创建这个索引
@Document(indexName = "items")
public class Item implements Serializable {
// SpringData标记当前属性为ES主键的注解
@Id
private Long id;
// SpringData标记title属性的支持分词的类似和相关分词器
@Field(type = FieldType.Text,
analyzer = "ik_max_word",
searchAnalyzer = "ik_max_word")
private String title;
// Keyword是不需要分词的字符串类型
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Keyword)
private String brand;
@Field(type = FieldType.Double)
private Double price;
// 图片地址不会称为搜索条件,所以不需要进行索引,不索引能节省一些数据空间
// 设置index=false 今后所有不会称为查询条件的列都照此配置
// 不索引,不代表不保存数据,数据本身仍然是保存在ES的
@Field(type = FieldType.Keyword,index = false)
private String imgPath;
// images/xxx/xxx/a09f-887ac-ac006-7128311231234
}
我们使用SpringData连接ES
需要使用SpringData框架对持久层的命名规则
持久层规范名称为repository(仓库),创建这个包,包中创建接口ItemRepository
// Repository 是spring家族框架对持久层的命名
@Repository
public interface ItemRepository extends
ElasticsearchRepository<Item,Long> {
// ItemRepository接口要继承SpringData提供的ElasticsearchRepository父接口
// 一旦继承,当前接口就会被识别为连接ES的持久层类,SpringData会自动为它生成基本增删改查方法
// ElasticsearchRepository<[关联的实体类名称],[实体类主键类型]>
}
创建test测试包
创建测试类
编写测试
// 测试类必须添加下面的注解,否则无法运行
@SpringBootTest
public class SpringEsTest {
// 装配ItemRepository
@Autowired
private ItemRepository itemRepository;
// 执行单增
@Test
void addOne(){
// 实例化一个Item对并赋值
Item item=new Item()
.setId(1L)
.setTitle("罗技激光无线游戏鼠标")
.setCategory("鼠标")
.setBrand("罗技")
.setPrice(168.0)
.setImgPath("/1.jpg");
// 利用SpringDataES提供的方法完成新增功能
itemRepository.save(item);
System.out.println("ok");
}
// 单查
@Test
void getOne(){
// SpringDataES提供了按id查询ES中数据的方法
// Optional是一个类似包装类的概念,查询结果封装到这个类型中
Optional<Item> optional=itemRepository.findById(1L);
Item item=optional.get();
System.out.println(item);
}
// 批量增
@Test
void addList(){
// 实例化一个List对象
List<Item> list=new ArrayList<>();
// 将要新增的对象保存在List中
list.add(new Item(2L,"罗技激光有线办公鼠标","鼠标",
"罗技",88.0,"/2.jpg"));
list.add(new Item(3L,"雷蛇机械无线游戏键盘","键盘",
"雷蛇",299.0,"/3.jpg"));
list.add(new Item(4L,"微软有线静音办公鼠标","鼠标",
"微软",205.0,"/4.jpg"));
list.add(new Item(5L,"罗技机械有线背光键盘","键盘",
"罗技",268.0,"/5.jpg"));
itemRepository.saveAll(list);
System.out.println("ok list");
}
// 全查
@Test
void getAll(){
// SpringDataES对ES全查(指定索引)返回数据的方法
Iterable<Item> items=itemRepository.findAll();
for(Item item : items){
System.out.println(item);
}
items.forEach(item -> System.out.println(item));
}
}
SpringData框架提供的基本增删改查方法并不能完全满足我们的业务需要
如果是针对当前Es数据,进行个性化的自定义查询,那还是需要自己编写查询代码
就像我们要实现根据关键词查询商品信息一样,完成类似数据库中的模糊查询
我们查询需求为输出所有数据中title属性包含"游戏"这个分词的商品信息
参考数据库中模糊查询
select * from item where title like '%游戏%'
我们使用SpringDataES进行查询,本质上还是相当于ES文档中执行的查询语句
在SpringData框架下,ItemRepository接口中实现更加简单
// SpringData自定义查询
// 可以通过遵循SpringData框架给定的格式定义方法名称,
// SpringData会根据方法名称自动生成查询语句
// query(查询):表示当前方法是一个查询方法,类似sql语句中的select
// Item/Items:确定要查询哪一个实体类,不带s的是单个对象,带s是集合
// By(通过/根据):标识开始设置查询条件,类似sql语句中的where
// Title:要查询的字段,可以根据查询条件修改为Item中的任何字段
// Matches:执行查询的操作,Matches表示字符串的匹配,而且这个匹配是支持分词的,类似sql语句的like
Iterable<Item> queryItemsByTitleMatches(String title);
下面可以开始在测试类中进行测试查询
//单条件查询
@Test
void queryOne(){
// 查询ES中items索引中,title字段包含"游戏"关键字的数据
Iterable<Item> items=itemRepository.queryItemsByTitleMatches("激光游戏");
items.forEach(item -> System.out.println(item));
}
上面代码运行时底层运行的查询语句为:
### 单条件搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {"match": { "title": "游戏" }}
}
在相对复杂的查询逻辑下
经常使用多个条件来定位查询需要的数据
这样就需要逻辑运算符"and"/"or"
ItemRepository接口中添加多条件的查询方法
// 多条件查询
// 多个条件之间我们需要使用And和Or来分隔,来表示他们的查询逻辑
// 方法的参数赋值是依据方法定义的参数顺序依次向条件中赋值的
Iterable<Item> queryItemsByTitleMatchesAndBrandMatches(
String title,String brand);
测试代码如下
// 多条件查询
@Test
void queryTwo(){
// 查询ES中items索引中,title字段包含"游戏"并且品牌是"罗技"的数据
Iterable<Item> items=itemRepository
.queryItemsByTitleMatchesAndBrandMatches("游戏","罗技");
items.forEach(item -> System.out.println(item));
}
底层运行的请求
### 多字段搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {
"bool": {
"must": [
{ "match": { "title": "游戏"}},
{ "match": { "brand": "罗技"}}
]
}
}
}
当查询条件关系为And时,查询语句关键字为must
当查询条件关系为Or时,查询语句关键字为should
默认情况下从ES中查询获得的数据排序依据是ES查询得出的相关性分数(score)
但是如果想改变这个排序就需要在查询方法上添加新的关键字
在ItemRepository接口添加具备排序功能的查询方法
// 排序查询
Iterable<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
String title,String brand);
测试
// 排序查询
@Test
void queryOrder(){
Iterable<Item> items=itemRepository
.queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
"游戏","罗技");
items.forEach(item -> System.out.println(item));
}
底层运行的代码
### 多字段搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {
"bool": {
"should": [
{ "match": { "title": "游戏"}},
{ "match": { "brand": "罗技"}}
]
}
},"sort":[{"price":"desc"}]
}
SpringData框架支持完成分页查询
需要在ItemRepository接口中修改方法的参数和返回值就可以实现
// 分页查询
// 返回值修改为Page类型,这个类型中包含了查询到的分页数据,和本次查询相关的分页信息
// 分页信息包含:当前页,总页数,总条数,每页条数,是否有上一页或下一页等
// 方法参数,在所有的参数后再添加一个新的参数类型,Pageable
Page<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
String title, String brand, Pageable pageable);
测试代码
// 分页查询
@Test
void queryPage(){
int pageNum=2; // 要查询的页码
int pageSize=2; // 每页包含的数据条数
Page<Item> page=itemRepository
.queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
"游戏","罗技", PageRequest.of(pageNum-1,pageSize));
page.forEach(item -> System.out.println(item));
// page对象中包含的分页和信息:
System.out.println("总页数:"+page.getTotalPages());
System.out.println("总条数:"+page.getTotalElements());
System.out.println("当前页:"+(page.getNumber()+1));
System.out.println("每页条数:"+page.getSize());
System.out.println("是否为首页:"+page.isFirst());
System.out.println("是否为末页:"+page.isLast());
需求分析
根据需求分析做数据库设计
概要设计
页面原型
详细设计(可选)
开发阶段
测试
部署上线
三阶段:酷鲨商城引流平台
SSM基本增删改查,完成的一个广告性质的展示页面
四阶段:酷鲨商城后台管理系统
单体管理项目的经典实现,完成商城的后台管理系统
五阶段:酷鲨商城前台访问页面(移动端)
微服务架构的项目,完成支持"高并发,高可用,高性能"的前台访问
1.分类搜索
2.商品列表
3.商品详情
4.购物车管理
5.新增订单和订单列表
6.搜索商品
7.高并发秒杀商品
java有比较长时间的演化和积淀
形成了Spring庞大的生态体系,在Spring中几乎可以找到所有业务的支持
java开发的项目一般都是中大型以上的项目
开发周期长,开发人数多,java开发的项目能够有最好的稳定性和安全性,也能够在微服务的支持下有更好的性能
一般java项目组人员组成 6~8人
一个项目经理(leader) 25K
一个技术总监 25K
两三个中坚力量 18-20K
两个初级程序员 8K
13万
开发周期
6-8个月
1.设计 1月
2.开发 2月
3.测试 3月
4.上线调试 1到2个月
100万
一线城市这样的项目至少160万
二线 120~130
三线 100左右
<<酷鲨商城数据库设计需求文档>>
里面主要是项目中数据库的设计解释和业务的解释
在csmall-finish的node文件夹下有压缩包
现在市面上开发模式主要有"传统开发模式"和"敏捷开发模式"
传统开发模式最经典的流程模型"瀑布模型"
严格的在项目开始时,定制计划,分析\设计\开发\测试\部署都有严格的时间节点
规定好每个阶段的输入和产出,每一个节点都依赖上一个阶段的产出才能进行,每个阶段的资源都是计划好的,可以让有限的资源得到充分的利用,重视的是标准化和文档的规范
文档详细,通过文档可以更简单的理解业务
每个阶段只关注下个阶段的对接和物料产出
每个阶段验收和检查有具体指标
资源利用有效性比较高
缺点
不适应项目需求的变化(严重缺点)
文档输出量大,因为文档导致的工作量也大
出效果的周期长
3.6.1敏捷开发模式
将项目开发的重点转换为用户的需求变化
将开发流程缩短,每一个小功能就是一个开发阶段
不断和用户沟通,分析用户需求来完善项目,强调的是项目的更新和迭代
优点
实时追踪用户需求,开发周期短,交付快,应对变化能力强
开发风险低,根据市场变化随时变化需求
缺点
文档详细程度远不如传统开发
很多代码会在项目迭代的过程中完全弃用,变成无用功
外包
中科软
文思海辉
博彦
外包一般不太卡学历,更注重项目业务和技术
外包公司服务的公司一般都是比较大的公司
不太容易能够接触核心代码 ,不算企业正式员工,不能长时间在外包
自研公司
开发自己的项目
能接触核心代码
有晋升机会
但是一般都是单体项目
不接触微服务,薪资会第一些
互联网公司
是行业的金字塔尖
薪资高
工作辛苦
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于
不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a
1.回顾.TransportServicepublicclassTransportServiceextendsAbstractLifecycleComponentTransportService:方法:1publicfinalTextendsTransportResponse>voidsendRequest(finalTransport.Connectionconnection,finalStringaction,finalTransportRequestrequest,finalTransportRequestOptionsoptions,TransportResponseHandlerT>
我有一个Rails应用程序,现在设置了ElasticSearch和Tiregem以在模型上进行搜索,我想知道我应该如何设置我的应用程序以对模型中的某些索引进行模糊字符串匹配。我将我的模型设置为索引标题、描述等内容,但我想对其中一些进行模糊字符串匹配,但我不确定在何处进行此操作。如果您想发表评论,我将在下面包含我的代码!谢谢!在Controller中:defsearch@resource=Resource.search(params[:q],:page=>(params[:page]||1),:per_page=>15,load:true)end在模型中:classResource'Us
美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-BasedService(LBS)业务场景对Elasticsearch的查询性能进行优化。该优化基于Run-LengthEncoding(RLE)设计了一款高效的倒排索引结构,使检索耗时(TP99)降低了84%。本文从问题分析、技术选型、优化方案等方面进行阐述,并给出最终灰度验证的结论。1.前言最近十年,Elasticsearch已经成为了最受欢迎的开源检索引擎,其作为离线数仓、近线检索、B端检索的经典基建,已沉淀了大量的实践案例及优化总结。然而在高并发、高可用、大数据量的C端场景,目前可参考的资料并不多。因此
开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建
文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就
我有一个关于配置elasticsearch以连接AWSelasticsearch服务以在生产环境中运行项目的问题。我的gem文件:gem'searchkick'gem'faraday_middleware-aws-signers-v4'gem'aws-sdk','~>2'gem"elasticsearch",">=1.0.15"引用:https://github.com/ankane/searchkick我的config/initializers/elasticsearch.rb文件:require"faraday_middleware/aws_signers_v4"ENV["ELAS
elasticsearch查看当前集群中的master节点是哪个需要使用_cat监控命令,具体如下。查看方法es主节点确定命令,以kibana上查看示例如下:GET_cat/nodesv返回结果示例如下:ipheap.percentram.percentcpuload_1mload_5mload_15mnode.rolemastername172.16.16.188529952.591.701.45mdi-elastic3172.16.16.187329950.990.991.19mdi-elastic2172.16.16.231699940.871.001.03mdi-elastic4172
我在查询中使用geo_distancefilter和tire,它工作正常:search.filter:geo_distance,:distance=>"#{request.distance}km",:location=>"#{request.lat},#{request.lng}"我预计结果会以某种方式包括到我用于过滤器的地理位置的计算距离。有没有办法告诉elasticsearch在响应中包含它,这样我就不必在ruby中为每个结果计算它?==更新==我在谷歌群组中的foundtheanswer:search.sortdoby"_geo_distance","location"=>"