Posted in Spring, Spring Cloud, 技术

Spring Cloud 那些事

Spring Cloud 那些事


Spring Cloud,分布式系统的一套工具,可用于构建微服务。针对 Spring Cloud 的学习和总结准备写系列文章。

代码共享在【springcloud-learning-example】,spring boot 实践学习案例,是 spring boot 初学者及核心技术巩固的最佳实践。

Github 地址:https://github.com/JeffLi1993/springcloud-learning-example

 

任何问题,上「Spring For All」找我!

 

文章如下:

『 Eureka 篇 - 服务治理 』Spring Cloud 之 Eureka 入门详解》
《Spring Cloud 之 Eureka 集群搭建(一)Eureka 注册中心服务集群》
《Spring Cloud 之 Eureka 集群搭建(二)Eureka 服务提供者和消费者集群『 Ribbon 篇 - 服务消费端负载均衡』
《Spring Cloud 之 Eureka 服务提供者使用 Ribbon 详解》

『 Hystrix 篇 - 服务容错 』


关注微信公众号,及时得到技术文章推送
Posted in Spring, Spring Data, 技术

深入浅出 spring-data-elasticsearch – 实战案例详解(四)

『  热烈的爱情到订婚早已是定点,婚一结一切了结。现在订了婚,彼此间还留着情感发展的余地,这是桩好事。- 《我们仨》 』

运行环境:JDK 7 或 8,Maven 3.0+
技术栈:SpringBoot 1.5+, Spring Data Elasticsearch 1.5+ ,ElasticSearch 2.3.2

本文提纲
一、搜索实战场景需求
二、运行 spring-data-elasticsearch-query 工程
三、spring-data-elasticsearch-query 工程代码详解

一、搜索实战场景需求
搜索的场景会很多,常用的搜索场景,需要搜索的字段很多,但每个字段匹配到后所占的权重又不同。比如电商网站的搜索,搜到商品名称和商品描述,自然商品名称的权重远远大于商品描述。而且单词匹配肯定不如短语匹配。这样就出现了新的需求,如何确定这些短语,即自然分词。那就利用分词器,即可得到所需要的短语,然后进行搜索。
下面介绍短语如何进行按权重分匹配搜索。

二、运行 spring-data-elasticsearch-query 工程
1. 后台起守护线程启动 Elasticsearch

cd elasticsearch-2.3.2/
./bin/elasticsearch -d

git clone 下载工程 springboot-elasticsearch ,项目地址见 GitHub – https://github.com/JeffLi1993/ … ample
下面开始运行工程步骤(Quick Start):
2. 项目结构介绍

org.spring.springboot.controller - Controllerorg.spring.springboot.repository - ES 数据操作层
org.spring.springboot.domain - 实体类
org.spring.springboot.service - ES 业务逻辑层
Application - 应用启动类
application.properties - 应用配置文件,应用启动会自动读取配置

本地启动的 ES ,就不需要改配置文件了。如果连测试 ES 服务地址,需要修改相应配置

3.编译工程
在项目根目录 spring-data-elasticsearch-query,运行 maven 指令:

mvn clean install

4.运行工程
右键运行 Application 应用启动类(位置:org/spring/springboot/Application.java)的 main 函数,这样就成功启动了 spring-data-elasticsearch-query 案例。
用 Postman 工具新增两个城市

a. 新增城市信息

POST http://127.0.0.1:8080/api/city
{
    "id”:"1",
    "score":"5",
    "name":"上海",
    "description":"上海是个热城市"
}
POST http://127.0.0.1:8080/api/city
{
    "id":"2",
    "score”:"4",
    "name”:”温岭",
    "description":”温岭是个沿海城市"
}

下面是实战搜索语句的接口:
GET http://localhost:8080/api/city … nt%3D城市
获取返回结果:
返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    },
    {
        "id": 1,
        "name": "上海",
        "description": "上海是个好城市",
        "score": 3
    }
]

应用的控制台中,日志打印出查询语句的 DSL :

 DSL  = 
 {
  "function_score" : {
    "functions" : [ {
      "filter" : {
        "match" : {
          "name" : {
            "query" : "城市",
            "type" : "phrase"
          }
        }
      },
      "weight" : 1000.0
    }, {
      "filter" : {
        "match" : {
          "description" : {
            "query" : "城市",
            "type" : "phrase"
          }
        }
      },
      "weight" : 500.0
    } ],
    "score_mode" : "sum",
    "min_score" : 10.0
  }
}

三、spring-data-elasticsearch-query 工程代码详解
具体代码见 GitHub – https://github.com/JeffLi1993/springboot-learning-example

1.pom.xml 依赖

<?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 http://maven.apache.org/xsd/ma ... gt%3B
    <modelVersion>4.0.0</modelVersion>
    <groupId>springboot</groupId>
    <artifactId>spring-data-elasticsearch-crud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-data-elasticsearch-crud :: spring-data-elasticsearch - 基本案例 </name>
    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>
    <dependencies>
        <!-- Spring Boot Elasticsearch 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!-- Spring Boot Web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

这里依赖的 spring-boot-starter-data-elasticsearch 版本是 1.5.1.RELEASE,对应的 spring-data-elasticsearch 版本是 2.1.0.RELEASE。对应官方文档:http://docs.spring.io/spring-d … html/。后面数据操作层都是通过该 spring-data-elasticsearch 提供的接口实现。

2. application.properties 配置 ES 地址

# ES
spring.data.elasticsearch.repositories.enabled = true
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300

默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口。
更多配置:
 spring.data.elasticsearch.cluster-name Elasticsearch    集群名。(默认值: elasticsearch)
 spring.data.elasticsearch.cluster-nodes    集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点。
 spring.data.elasticsearch.propertie     用来配置客户端的额外属性。
 spring.data.elasticsearch.repositories.enabled     开启 Elasticsearch 仓库。(默认值:true。)

3. ES 数据操作层

/**
 * ES 操作类
 * <p>
 * Created by bysocket on 17/05/2017.
 */
public interface CityRepository extends ElasticsearchRepository<City, Long> {
}

接口只要继承 ElasticsearchRepository 接口类即可,具体使用的是该接口的方法:

    Iterable<T> search(QueryBuilder query);
    Page<T> search(QueryBuilder query, Pageable pageable);
    Page<T> search(SearchQuery searchQuery);
    Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);

4. 实体类

/**
 * 城市实体类
 * <p>
 * Created by bysocket on 03/05/2017.
 */
@Document(indexName = "province", type = "city")
public class City implements Serializable {
    private static final long serialVersionUID = -1L;
    /**
     * 城市编号
     */
    private Long id;
    /**
     * 城市名称
     */
    private String name;
    /**
     * 描述
     */
    private String description;
    /**
     * 城市评分
     */
    private Integer score;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Integer getScore() {
        return score;
    }
    public void setScore(Integer score) {
        this.score = score;
    }
}

注意
a. City 属性名不支持驼峰式。
b. indexName 配置必须是全部小写,不然会出异常。
org.elasticsearch.indices.InvalidIndexNameException: Invalid index name [provinceIndex], must be lowercase

5. 城市 ES 业务逻辑实现类
代码如下:

/**
 * 城市 ES 业务逻辑实现类
 * <p>
 * Created by bysocket on 20/06/2017.
 */
@Service
public class CityESServiceImpl implements CityService {
    private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class);
    /* 分页参数 */
    Integer PAGE_SIZE = 12;          // 每页数量
    Integer DEFAULT_PAGE_NUMBER = 0; // 默认当前页码
    /* 搜索模式 */
    String SCORE_MODE_SUM = "sum"; // 权重分求和模式
    Float  MIN_SCORE = 10.0F;      // 由于无相关性的分值默认为 1 ,设置权重分最小值为 10
    @Autowired
    CityRepository cityRepository; // ES 操作类
    public Long saveCity(City city) {
        City cityResult = cityRepository.save(city);
        return cityResult.getId();
    }
    @Override
    public List<City> searchCity(Integer pageNumber, Integer pageSize, String searchContent) {
        // 校验分页参数
        if (pageSize == null || pageSize <= 0) {
            pageSize = PAGE_SIZE;
        }
        if (pageNumber == null || pageNumber < DEFAULT_PAGE_NUMBER) {
            pageNumber = DEFAULT_PAGE_NUMBER;
        }
        LOGGER.info("\n searchCity: searchContent [" + searchContent + "] \n ");
        // 构建搜索查询
        SearchQuery searchQuery = getCitySearchQuery(pageNumber,pageSize,searchContent);
        LOGGER.info("\n searchCity: searchContent [" + searchContent + "] \n DSL  = \n " + searchQuery.getQuery().toString());
        Page<City> cityPage = cityRepository.search(searchQuery);
        return cityPage.getContent();
    }
    /**
     * 根据搜索词构造搜索查询语句
     *
     * 代码流程:
     *      - 权重分查询
     *      - 短语匹配
     *      - 设置权重分最小值
     *      - 设置分页参数
     *
     * @param pageNumber 当前页码
     * @param pageSize 每页大小
     * @param searchContent 搜索内容
     * @return
     */
    private SearchQuery getCitySearchQuery(Integer pageNumber, Integer pageSize,String searchContent) {
        // 短语匹配到的搜索词,求和模式累加权重分
        // 权重分查询 https://www.elastic.co/guide/c ... .html
        //   - 短语匹配 https://www.elastic.co/guide/c ... .html
        //   - 字段对应权重分设置,可以优化成 enum
        //   - 由于无相关性的分值默认为 1 ,设置权重分最小值为 10
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchPhraseQuery("name", searchContent),
                ScoreFunctionBuilders.weightFactorFunction(1000))
                .add(QueryBuilders.matchPhraseQuery("description", searchContent),
                ScoreFunctionBuilders.weightFactorFunction(500))
                .scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE);
        // 分页参数
        Pageable pageable = new PageRequest(pageNumber, pageSize);
        return new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder).build();
    }
}

可以看到该过程实现了,短语精准匹配以及匹配到根据字段权重分求和,从而实现按权重搜索查询。代码流程如下:
– 权重分查询
– 短语匹配
– 设置权重分最小值
– 设置分页参数

注意:
– 字段对应权重分设置,可以优化成 enum
– 由于无相关性的分值默认为 1 ,设置权重分最小值为 10

权重分查询文档:https://www.elastic.co/guide/c … .html
短语匹配文档: https://www.elastic.co/guide/c … .html

四、小结
Elasticsearch 还提供很多高级的搜索功能。这里提供下需要经常逛的相关网站:
Elasticsearch 中文社区 https://elasticsearch.cn/topic/elasticsearch
Elasticsearch: 权威指南-在线版 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!

Posted in Spring, Spring Data, 技术

深入浅出 spring-data-elasticsearch – 基本案例详解(三

『  风云说:能分享自己职位的知识的领导是个好领导。 』
运行环境:JDK 7 或 8,Maven 3.0+
技术栈:SpringBoot 1.5+, Spring Data Elasticsearch 1.5+ ,ElasticSearch 2.3.2
本文提纲
一、spring-data-elasticsearch-crud 的工程介绍
二、运行 spring-data-elasticsearch-crud 工程
三、spring-data-elasticsearch-crud 工程代码详解

一、spring-data-elasticsearch-crud 的工程介绍
spring-data-elasticsearch-crud 的工程,介绍 Spring Data Elasticsearch 简单的 ES 操作。Spring Data Elasticsearch 可以跟 JPA 进行类比。其使用方法也很简单。

二、运行 spring-data-elasticsearch-crud 工程
注意的是这里使用的是 ElasticSearch 2.3.2。是因为版本对应关系 https://github.com/spring-projects/spring-data-elasticsearch/wiki/Spring-Data-Elasticsearch—Spring-Boot—version-matrix;

Spring Boot Version (x)    Spring Data Elasticsearch Version (y)    Elasticsearch Version (z)
x <= 1.3.5    y <= 1.3.4    z <= 1.7.2*
x >= 1.4.x    2.0.0 <=y < 5.0.0**    2.0.0 <= z < 5.0.0**
*  – 只需要你修改下对应的 pom 文件版本号
** – 下一个 ES 的版本会有重大的更新

1. 后台起守护线程启动 Elasticsearch

cd elasticsearch-2.3.2/
./bin/elasticsearch -d

git clone 下载工程 springboot-elasticsearch ,项目地址见 GitHub – https://github.com/JeffLi1993/ … ample
下面开始运行工程步骤(Quick Start):

2. 项目结构介绍

org.spring.springboot.controller - Controllerorg.spring.springboot.repository - ES 数据操作层
org.spring.springboot.domain - 实体类
org.spring.springboot.service - ES 业务逻辑层
Application - 应用启动类
application.properties - 应用配置文件,应用启动会自动读取配置

本地启动的 ES ,就不需要改配置文件了。如果连测试 ES 服务地址,需要修改相应配置

3.编译工程
在项目根目录 spring-data-elasticsearch-crud,运行 maven 指令:

mvn clean install

4.运行工程
右键运行 Application 应用启动类(位置:/springboot-learning-example/springboot-elasticsearch/src/main/java/org/spring/springboot/Application.java)的 main 函数,这样就成功启动了 springboot-elasticsearch 案例。
用 Postman 工具新增两个城市

a. 新增城市信息

POST http://127.0.0.1:8080/api/city
{
    "id”:"1",
    "score":"5",
    "name":"上海",
    "description":"上海是个热城市"
}

 

POST http://127.0.0.1:8080/api/city
{
    "id":"2",
    "score”:"4",
    "name”:”温岭",
    "description":”温岭是个沿海城市"
}

可以打开 ES 可视化工具 head 插件:http://localhost:9200/_plugin/head/
(如果不知道怎么安装,请查阅 《Elasticsearch 和插件 elasticsearch-head 安装详解》 http://www.bysocket.com/?p=1744 。)
在「数据浏览」tab,可以查阅到 ES 中数据是否被插入,插入后的数据格式如下:

{
"_index": "cityindex",
"_type": "city",
"_id": "1",
"_version": 1,
"_score": 1,
"_source": {
  "id":"2",
    "score”:"4",
    "name”:”温岭",
    "description":”温岭是个沿海城市"
}
}

下面是基本查询语句的接口:
a. 普通查询,查询城市描述

GET http://localhost:8080/api/city ... on%3D温岭

返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    }
]

b. AND 语句查询

GET http://localhost:8080/api/city ... on%3D温岭&score=4

返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    }
]

如果换成 score=5 ,就没有结果了。

c. OR 语句查询

GET http://localhost:8080/api/city ... on%3D上海&score=4

返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    },
    {
        "id": 1,
        "name": "上海",
        "description": "上海是个好城市",
        "score": 3
    }
]

d. NOT 语句查询

GET http://localhost:8080/api/city ... on%3D温州

返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    },
    {
        "id": 1,
        "name": "上海",
        "description": "上海是个好城市",
        "score": 3
    }
]

e. LIKE 语句查询

GET http://localhost:8080/api/city ... on%3D城市

返回 JSON 如下:

[
    {
        "id": 2,
        "name": "温岭",
        "description": "温岭是个沿海城市",
        "score": 4
    },
    {
        "id": 1,
        "name": "上海",
        "description": "上海是个好城市",
        "score": 3
    }
]

三、spring-data-elasticsearch-crud 工程代码详解
具体代码见 GitHub – https://github.com/JeffLi1993/springboot-learning-example

1.pom.xml 依赖

<?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 http://maven.apache.org/xsd/ma ... gt%3B
    <modelVersion>4.0.0</modelVersion>
    <groupId>springboot</groupId>
    <artifactId>spring-data-elasticsearch-crud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-data-elasticsearch-crud :: spring-data-elasticsearch - 基本案例 </name>
    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>
    <dependencies>
        <!-- Spring Boot Elasticsearch 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!-- Spring Boot Web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

这里依赖的 spring-boot-starter-data-elasticsearch 版本是 1.5.1.RELEASE,对应的 spring-data-elasticsearch 版本是 2.1.0.RELEASE。对应官方文档:http://docs.spring.io/spring-d … html/。后面数据操作层都是通过该 spring-data-elasticsearch 提供的接口实现。

2. application.properties 配置 ES 地址

# ES
spring.data.elasticsearch.repositories.enabled = true
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300
默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口。

更多配置:
 spring.data.elasticsearch.cluster-name Elasticsearch    集群名。(默认值: elasticsearch)
 spring.data.elasticsearch.cluster-nodes    集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点。
 spring.data.elasticsearch.propertie     用来配置客户端的额外属性。
 spring.data.elasticsearch.repositories.enabled     开启 Elasticsearch 仓库。(默认值:true。)

3. ES 数据操作层

/**
 * ES 操作类
 * <p>
 * Created by bysocket on 17/05/2017.
 */
public interface CityRepository extends ElasticsearchRepository<City, Long> {
    /**
     * AND 语句查询
     *
     * @param description
     * @param score
     * @return
     */
    List<City> findByDescriptionAndScore(String description, Integer score);
    /**
     * OR 语句查询
     *
     * @param description
     * @param score
     * @return
     */
    List<City> findByDescriptionOrScore(String description, Integer score);
    /**
     * 查询城市描述
     *
     * 等同于下面代码
     * @Query("{\"bool\" : {\"must\" : {\"term\" : {\"description\" : \"?0\"}}}}")
     * Page<City> findByDescription(String description, Pageable pageable);
     *
     * @param description
     * @param page
     * @return
     */
    Page<City> findByDescription(String description, Pageable page);
    /**
     * NOT 语句查询
     *
     * @param description
     * @param page
     * @return
     */
    Page<City> findByDescriptionNot(String description, Pageable page);
    /**
     * LIKE 语句查询
     *
     * @param description
     * @param page
     * @return
     */
    Page<City> findByDescriptionLike(String description, Pageable page);
}

接口只要继承 ElasticsearchRepository 类即可。默认会提供很多实现,比如 CRUD 和搜索相关的实现。类似于 JPA 读取数据,是使用 CrudRepository 进行操作 ES 数据。支持的默认方法有: count(), findAll(), findOne(ID), delete(ID), deleteAll(), exists(ID), save(DomainObject), save(Iterable<DomainObject>)。

另外可以看出,接口的命名是遵循规范的。常用命名规则如下:
关键字     方法命名
And          findByNameAndPwd
Or             findByNameOrSex
Is              findById
Between   findByIdBetween
Like           findByNameLike
NotLike     findByNameNotLike
OrderBy    findByIdOrderByXDesc
Not           findByNameNot

4. 实体类

/**
 * 城市实体类
 * <p>
 * Created by bysocket on 03/05/2017.
 */
@Document(indexName = "province", type = "city")
public class City implements Serializable {
    private static final long serialVersionUID = -1L;
    /**
     * 城市编号
     */
    private Long id;
    /**
     * 城市名称
     */
    private String name;
    /**
     * 描述
     */
    private String description;
    /**
     * 城市评分
     */
    private Integer score;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Integer getScore() {
        return score;
    }
    public void setScore(Integer score) {
        this.score = score;
    }
}

注意
a. City 属性名不支持驼峰式。
b. indexName 配置必须是全部小写,不然会出异常。
org.elasticsearch.indices.InvalidIndexNameException: Invalid index name [provinceIndex], must be lowercase

四、小结
预告下
下一篇《深入浅出 spring-data-elasticsearch – 实战案例详解》,会带来实战项目中涉及到的权重分 & 短语精准匹配的讲解。

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!

Posted in Spring, Spring Data, 技术

深入浅出 spring-data-elasticsearch 系列 – 概述及入门(二)

本文目录
一、spring-data-elasticsearch 是什么?
1.1 Spring Data
1.2 Spring Data Elasticsearch
二、spring-data-elasticsearch 快速入门
2.1 pom.xml 依赖
2.2 ElasticsearchRepository
2.3 ElasticsearchTemplate
2.4 使用案例
三、spring-data-elasticsearch 和 elasticsearch 版本
四、小结

这里我们只是把人生大致分成“学习阶段”以及之后的“工作阶段”。
-《未来简史》

一、spring-data-elasticsearch 是什么?
1.1 Spring Data
要了解 spring-data-elasticsearch 是什么,首先了解什么是 Spring Data。
Spring Data 基于 Spring 为数据访问提供一种相似且一致性的编程模型,并保存底层数据存储的。

1.2 Spring Data Elasticsearch
spring-data-elasticsearch 是 Spring Data 的 Community modules 之一,是 Spring Data 对 Elasticsearch 引擎的实现。
Elasticsearch 默认提供轻量级的 HTTP Restful 接口形式的访问。相对来说,使用 HTTP Client 调用也很简单。但 spring-data-elasticsearch 可以更快的支持构建在 Spring 应用上,比如在 application.properties 配置 ES 节点信息和 spring-boot-starter-data-elasticsearch 依赖,直接在 Spring Boot 应用上使用。

二、spring-data-elasticsearch 快速入门
2.1 pom.xml 依赖

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
    <version>x.y.z.RELEASE</version>
</dependency>

2.2 ElasticsearchRepository
ES 通用的存储接口的一种默认实现。Spring 根据接口定义的方法名,具体执行对应的数据存储实现。
ElasticsearchRepository 继承 ElasticsearchCrudRepository ,ElasticsearchCrudRepository 继承 PagingAndSortingRepository。所以一般 CRUD 带分页已经支持。如图:

esr.png

2.3 ElasticsearchTemplate
ES 数据操作的中心支持类。和 JdbcTemplate 一样,几乎所有操作都可以使用 ElasticsearchTemplate 来完成。
ElasticsearchTemplate 实现了 ElasticsearchOperations 和 ApplicationContextAware 接口。ElasticsearchOperations 接口提供了 ES 相关的操作,并将 ElasticsearchTemplate 加入到 Spring 上下文。如图:

est.png

2.4 使用案例
拿官方案例来吧,详细介绍了 Book ES 对象的接口实现。
可以看出,book 拥有 name 和 price 两个属性。下面支持  name 和 price 列表 ES 查询,分页查询,范围查询等。还有可以利用注解实现 DSL 操作。

    public interface BookRepository extends Repository<Book, String> {
        List<Book> findByNameAndPrice(String name, Integer price);
        List<Book> findByNameOrPrice(String name, Integer price);
        Page<Book> findByName(String name,Pageable page);
        Page<Book> findByNameNot(String name,Pageable page);
        Page<Book> findByPriceBetween(int price,Pageable page);
        Page<Book> findByNameLike(String name,Pageable page);
        @Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}")
        Page<Book> findByMessage(String message, Pageable pageable);
    }

三、spring-data-elasticsearch 和 elasticsearch 版本
SpringBoot 1.5+ 目前仅支持 ElasticSearch 2.3.2,所以如果想要使用最新的 ES。可以通过默认的轻量级的 HTTP 去调用实现。其版本对应如下:

spring data elasticsearch    elasticsearch
3.0.0.BUILD-SNAPSHOT    5.4.0
2.0.4.RELEASE                    2.4.0
2.0.0.RELEASE                    2.2.0
1.4.0.M1                               1.7.3
1.3.0.RELEASE                    1.5.2
1.2.0.RELEASE                    1.4.4
1.1.0.RELEASE                    1.3.2
1.0.0.RELEASE                    1.1.1

四、小结
本小结介绍了 spring-data-elasticsearch 是概述以及它的入门,还有 spring-data-elasticsearch 核心接口及版本的情况。

资料:
项目地址
https://github.com/spring-proj … earch
官方文档
http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/

本文作者: 泥瓦匠
原文链接: http://www.bysocket.com
版权归作者所有,转载请注明出处

Posted in Spring, Spring Data, 技术

深入浅出 spring-data-elasticsearch 之 ElasticSearch 架构初探(一)

本文目录
一、Elasticsearch 基本术语
1.1 文档(Document)、索引(Index)、类型(Type)文档三要素
1.2 集群(Cluster)、节点(Node)、分片(Shard)分布式三要素
二、Elasticsearch 工作原理
2.1 文档存储的路由
2.2 如何健康检查
2.3 如何水平扩容
三、小结

Spring For All 社区spring4all.com)是新组建的关于 Spring 的纯技术交流社区。来社区找我吧。

一、Elasticsearch 基本术语

1.1 文档(Document)、索引(Index)、类型(Type)文档三要素
文档(Document)
文档,在面向对象观念就是一个对象。在 ES 里面,是一个大 JSON 对象,是指定了唯一 ID 的最底层或者根对象。文档的位置由 _index、_type 和 _id 唯一标识。

索引(Index)
索引,用于区分文档成组,即分到一组的文档集合。索引,用于存储文档和使文档可被搜索。比如项目存索引 project 里面,交易存索引 sales 等。

类型(Type)
类型,用于区分索引中的文档,即在索引中对数据逻辑分区。比如索引 project 的项目数据,根据项目类型 ui 项目、插画项目等进行区分。

和关系型数据库 MySQL 做个类比:
Document 类似于 Record
Type 类似于 Table
Index 类似于 Database

1.2 集群(Cluster)、节点(Node)、分片(Shard)分布式三要素
集群(Cluster)
服务器集群大家都知道,这里 ES 也是类似的。多个 ElasticSearch 运行实例(节点)组合的组合体是 ElasticSearch 集群。
ElasticSearch 是天然的分布式,通过水平扩容为集群添加更多节点。
集群是去中心化的,有一个主节点(Master)。主节点是动态选举,因此不会出现单点故障。

那分片和节点的配置呢?

节点(Node)
一个 ElasticSearch 运行实例就是节点。顺着集群来,任何节点都可以被选举成为主节点。主节点负责集群内所以变更,比如索引的增加、删除等。所以集群不会因为主节点流量的增大成为瓶颈。因为任何节点都会成为主节点。
下面有 3 个节点,第 1 个节点有:2 个主分片和 1 个副分片。如图:

那么,只有一个节点的 ElasticSearch 服务会存在瓶颈。如图:

分片(Shard)
分片,是 ES 节点中最小的工作单元。分片仅仅保存全部数据的一部分,分片的集合是 ES 的索引。分片包括主分片和副分片,主分片是副分片的拷贝。主分片和副分片地工作基本没有大的区别。
在索引中全文搜索,然后会查询到每个分片,将每个分配的结果进行全局地收集处理,并返回。

二、Elasticsearch 工作原理

2.1 文档存储的路由
当索引到一个文档(如:报价系统),具体的文档数据(如:报价数据)会存储到一个分片。具体文档数据会被切分,并分别存储在分片 1 或者 分片 2 … 那么如何确定存在哪个分片呢?

存储路由过程由下面地公式决定:

shard = hash(routing) % number_of_primary_shards

routing 是可变值,支持自定义,默认文档 _id。
hash 函数生成数字,经过取余算法得到余数,那么这个余数就是分片的位置。
这是不是有点负载均衡的类似。

2.2 如何健康检查
集群名,集群的健康状态

GET http://127.0.0.1:9200/_cluster/stats
{
"cluster_name": "elasticsearch",
"status": "green",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}

status 字段是需要我们关心的。状态可能是下列三个值之一:

green
所有的主分片和副本分片都已分配。你的集群是 100% 可用的。
yellow
所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。高可用会弱化把 yellow 想象成一个需要及时调查的警告。
red
至少一个主分片(以及它的全部副本)都在缺失中。这意味着你在缺少数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常。

active_primary_shards 集群中的主分片数量
active_shards 所有分片的汇总值
relocating_shards 显示当前正在从一个节点迁往其他节点的分片的数量。通常来说应该是 0,不过在 Elasticsearch 发现集群不太均衡时,该值会上涨。比如说:添加了一个新节点,或者下线了一个节点。
initializing_shards 刚刚创建的分片的个数。
unassigned_shards 已经在集群状态中存在的分片。

2.3 如何水平扩容
主分片在索引创建已经确定。读操作可以同时被主分片和副分片处理。因此,更多的分片,会拥有更高的吞吐量。自然,需要增加更多的硬件资源支持吞吐量。说明,这里无法提高性能,因为每个分片获得的资源会变少。动态调整副本分片数,按需伸缩集群,比如把副本数默认值为 1 增加到 2:

PUT /blogs/_settings
{
"number_of_replicas" : 2
}

三、小结
简单初探了下 ElasticSearch 的相关内容。后面会主要落地到实战,关于 spring-data-elasticsearch 这块的实战。

最后,《 深入浅出 spring-data-elasticsearch 》小连载目录如下:
深入浅出 spring-data-elasticsearch – ElasticSearch 架构初探(一)
深入浅出 spring-data-elasticsearch – 概述(二)
深入浅出 spring-data-elasticsearch – 基本案例详解(三)
深入浅出 spring-data-elasticsearch – 复杂案例详解(四)
深入浅出 spring-data-elasticsearch – 架构原理以及源码浅析(五)

资料:
官方《Elasticsearch: 权威指南》
https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

欢迎扫一扫我的公众号关注 — 及时得到博客订阅哦!
— http://www.bysocket.com/ —
— https://github.com/JeffLi1993 —

Posted in Spring, Spring Boot, Spring Cloud, 技术

SpringCloud 中文社区 转型 Spring4All 欢迎您的加入

相信关注我们Spring Cloud中文社区(bbs.springcloud.com.cn)的朋友们最近已经在最新的横幅中发现了一个全新的社区:spring4all.com,相信从名字大家也能猜到该域名寓意Spring For All,那么我们为什么要重新创建这样一个社区呢?

关于 Spring For All

截止至今天,我们的论坛注册用户也已经有 1000+ 名了,在维护 Spring Cloud 中文社区的过程中,我们收到了各种各样关于 Spring Boot 和 Spring Cloud 的不同问题。虽然我们论坛的核心定位在 Spring Cloud,但是很多问题并非由 Spring Cloud 本身负责的,而是其他 Spring 项目所负责。那么为了说清楚这些内容,还是需要用户对Spring的其他相关项目有一定的了解之后才能弄明白其基本原理。

事实上,我们在实战过程中,就算采用了 Spring Boot 和 Spring Cloud 来构建微服务系统,其实我们的开发人员和架构师要学习的远不止这两个框架内容。就从 Spring Boot 而言,它虽然提供了快速构建微服务的能力,但是当开发具体业务功能时,我们还是需要 Spring 的其他框架,比如 Spring MVC, Spring Data 等。所以,我们为了用好 Spring Boot 和 Spring Cloud,对于 Spring 的其他项目根据自身的业务需要,不得不去深入了解它们的使用方法,才能帮助我们构建起可靠的微服务系统。

Spring 社区提供的框架从最初的 Spring Framework 发展至今已经形成了一套非常强大而复杂的技术体系。我们现在使用 Spring 与以往使用 Spring 的方式也有所不同了,以往我们需要整合各种不同的第三方框架来实现我们的业务,在 Spring Boot 和其他一些 Spring 项目的帮助下,我们通过 Spring 的封装可以非常方便的使用其他框架提供的功能。方便的同时也带了其他的问题,我们需要学习Spring封装后的这些框架如何来使用。而目前国内Spring技术非常缺乏这方面的分享内容,所以Spring For All社区的萌芽想法就出现了。

由于一些变故,算是促成了该社区的诞生,Spring For All,这里分享关于Spring的一切,我们旨在做最纯粹的技术交流社区,不夸大、不装逼,最中国最大的Spring知识集中地。

由于Spring For All社区的建立,我们将减少对 bbs.springcloud.com.cn的维护精力。原有用户可以至spring4all.com来分享内容和交流疑惑,这里除了我(程序猿DD)之外,还有《Spring Cloud与Docker微服务架构实战》作者周立等诸多技术大牛和开源爱好者为大家答疑解惑。所以,Spring Cloud的关注用户,请看过来吧,你千万不能错过的技术交流平台:spring4all.com

目前社区已初具规模,QQ群交流总人数达 9000 左右 人,更多内容会不断进行完善(免费教程、免费视频),有兴趣的用户可以加下面的QQ群参与讨论和学习:

Spring For All 社区 ① 365234583(满)
Spring For All 社区 ② 123013854(满)
Spring For All 社区 ③ 290714704
Spring For All 社区 ④ 112133511
Spring For All 社区 ⑤ 157525002(满)
Spring For All 社区 ⑥ 564840207
Spring For All 社区 ⑦ 470962790(满)
Spring For All 社区 ⑧ 613456104(满)
Spring For All 社区 ⑨ 534583667
Spring For All 社区 ⑩ 210742970(满)

Posted in 清文

为什么要看点正常的书

为什么要看点正常的书
因为两个人的时候
看书的时间就少了

为什么读书呢
这大家都至少读过
讲起来难为情
但要讲也不好讲

所以什么是正常的书
一本对你好的书

什么是一本对你好的书
和你那时候的心境有关
就想想吃什么去吃一样

读什么书
每本书不同时候
看会有不同的感触

但中国旧书
是经不起读的
英文好看看外籍
英文不好看看翻译好的
也不错

没有好书坏书
只有感觉看,又舍不得看完的书
只有感觉看,以后还可能在看的书

因为书中的句子、故事章节
让我思考
很多里面出来的 ideas
是遇到问题
遇到事
处理方式的演变

是自己与自己的沟通
所以要静下心来看

我没看过玄幻
我怕和吸毒一样上瘾
浮躁的时候是不能得到任何的

书中自有千钟粟
书中自有黄金屋
书中自有颜如玉

就是说
读书可以做官发财
读书可以不住茅房
读书可以娶得漂亮年轻妹子

就这样
520
你懂的

顺便撩下
关注的
2500 +
读者

遇见
快乐

Posted in Spring, Spring Boot, 技术

Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!

『 预见未来最好的方式就是亲手创造未来 – 《史蒂夫·乔布斯传》 』

运行环境:JDK 7 或 8,Maven 3.0+
技术栈:SpringBoot 1.5+,ElasticSearch 2.3.2

本文提纲
一、ES 的使用场景
二、运行 springboot-elasticsearch 工程
三、springboot-elasticsearch 工程代码详解

一、ES 的使用场景

简单说,ElasticSearch(简称 ES)是搜索引擎,是结构化数据的分布式搜索引擎。在《Elasticsearch 和插件 elasticsearch-head 安装详解》  和 《Elasticsearch 默认配置 IK 及 Java AnalyzeRequestBuilder 使用》 我详细的介绍了如何安装,初步使用了 IK 分词器。这里,我主要讲下 SpringBoot 工程中如何使用 ElasticSearch。

ES 的使用场景大致分为两块
1. 全文检索。加上分词(IK 是其中一个)、拼音插件等可以成为强大的全文搜索引擎。
2. 日志统计分析。可以实时动态分析海量日志数据。

二、运行 springboot-elasticsearch 工程

注意的是这里使用的是 ElasticSearch 2.3.2。是因为版本对应关系

Spring Boot Version (x) Spring Data Elasticsearch Version (y) Elasticsearch Version (z)
x <= 1.3.5 y <= 1.3.4 z <= 1.7.2* x >= 1.4.x 2.0.0 <=y < 5.0.0** 2.0.0 <= z < 5.0.0**
* - 只需要你修改下对应的 pom 文件版本号
** - 下一个 ES 的版本会有重大的更新

git clone 下载工程 springboot-elasticsearch ,项目地址见 GitHub – https://github.com/JeffLi1993/springboot-learning-example。

1. 后台起守护线程启动 Elasticsearch

cd elasticsearch-2.3.2/
./bin/elasticsearch -d

下面开始运行工程步骤(Quick Start):

2. 项目结构介绍

org.spring.springboot.controller - Controller 层
org.spring.springboot.repository - ES 数据操作层
org.spring.springboot.domain - 实体类
org.spring.springboot.service - ES 业务逻辑层
Application - 应用启动类
application.properties - 应用配置文件,应用启动会自动读取配置

本地启动的 ES ,就不需要改配置文件了。如果连测试 ES 服务地址,需要修改相应配置

3.编译工程
在项目根目录 springboot-elasticsearch,运行 maven 指令:

mvn clean install

4.运行工程
右键运行 Application 应用启动类(位置:/springboot-learning-example/springboot-elasticsearch/src/main/java/org/spring/springboot/Application.java)的 main 函数,这样就成功启动了 springboot-elasticsearch 案例。

用 Postman 工具新增两个城市
新增城市信息

POST http://127.0.0.1:8080/api/city
{
"id":"1",
"provinceid":"1",
"cityname":"温岭",
"description":"温岭是个好城市"
}

POST http://127.0.0.1:8080/api/city
{
"id":"2",
"provinceid":"2",
"cityname":"温州",
"description":"温州是个热城市"
}

可以打开 ES 可视化工具 head 插件:http://localhost:9200/_plugin/head/:
(如果不知道怎么安装,请查阅 《Elasticsearch 和插件 elasticsearch-head 安装详解》 。)
在「数据浏览」tab,可以查阅到 ES 中数据是否被插入,插入后的数据格式如下:

{
"_index": "cityindex",
"_type": "city",
"_id": "1",
"_version": 1,
"_score": 1,
"_source": {
"id": 1,
"provinceid": 1,
"cityname": "温岭",
"description": "温岭是个好城市"
}
}

下面验证下权重分查询搜索接口的实现:
GET http://localhost:8080/api/city/search?pageNumber=0&pageSize=10&searchContent=温岭
数据是会出现

[
{
"id": 1,
"provinceid": 1,
"cityname": "温岭",
"description": "温岭是个好城市"
},
{
"id": 2,
"provinceid": 2,
"cityname": "温州",
"description": "温州是个热城市"
}
]

从启动后台 Console 可以看出,打印出来对应的 DSL 语句:

{
"function_score" : {
"functions" : [ {
"filter" : {
"bool" : {
"should" : {
"match" : {
"cityname" : {
"query" : "温岭",
"type" : "boolean"
}
}
}
}
},
"weight" : 1000.0
}, {
"filter" : {
"bool" : {
"should" : {
"match" : {
"description" : {
"query" : "温岭",
"type" : "boolean"
}
}
}
}
},
"weight" : 100.0
} ]
}
}

为什么会出现 温州 城市呢?因为 function score query 权重分查询,无相关的数据默认分值为 1。如果想除去,设置一个 setMinScore 分值即可。

三、springboot-elasticsearch 工程代码详解

具体代码见 GitHubhttps://github.com/JeffLi1993/springboot-learning-example
1.pom.xml 依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>springboot</groupId>
    <artifactId>springboot-elasticsearch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-elasticsearch :: 整合 Elasticsearch </name>

    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>

    <dependencies>

        <!-- Spring Boot Elasticsearch 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

        <!-- Spring Boot Web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

这里依赖的 spring-boot-starter-data-elasticsearch 版本是 1.5.1.RELEASE,对应的 spring-data-elasticsearch 版本是 2.1.0.RELEASE。后面数据操作层都是通过该 spring-data-elasticsearch 提供的接口实现。

操作对应官方文档:http://docs.spring.io/spring-data/elasticsearch/docs/2.1.0.RELEASE/reference/html/。

2. application.properties 配置 ES 地址

# ES
spring.data.elasticsearch.repositories.enabled = true
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300

默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口。
更多配置:

spring.data.elasticsearch.cluster-name Elasticsearch 集群名。(默认值: elasticsearch)
spring.data.elasticsearch.cluster-nodes 集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点。
spring.data.elasticsearch.propertie 用来配置客户端的额外属性。
spring.data.elasticsearch.repositories.enabled 开启 Elasticsearch 仓库。(默认值:true。)

3. ES 数据操作层

@Repository
public interface CityRepository extends ElasticsearchRepository<City,Long> {


}

接口只要继承 ElasticsearchRepository 类即可。默认会提供很多实现,比如 CRUD 和搜索相关的实现。

4. 实体类

@Document(indexName = "cityindex", type = "city")
public class City implements Serializable{

    private static final long serialVersionUID = -1L;

    /**
     * 城市编号
     */
    private Long id;

    /**
     * 省份编号
     */
    private Long provinceid;

    /**
     * 城市名称
     */
    private String cityname;

    /**
     * 描述
     */
    private String description;
}

注意
index 配置必须是全部小写,不然会暴异常。
org.elasticsearch.indices.InvalidIndexNameException: Invalid index name [cityIndex], must be lowercase

5. ES 业务逻辑层

/**
 * 城市 ES 业务逻辑实现类
 *
 * Created by bysocket on 07/02/2017.
 */
@Service
public class CityESServiceImpl implements CityService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class);

    @Autowired
    CityRepository cityRepository;

    @Override
    public Long saveCity(City city) {

        City cityResult = cityRepository.save(city);
        return cityResult.getId();
    }

    @Override
    public List<City> searchCity(Integer pageNumber,
                                 Integer pageSize,
                                 String searchContent) {
        // 分页参数
        Pageable pageable = new PageRequest(pageNumber, pageSize);

        // Function Score Query
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("cityname", searchContent)),
                    ScoreFunctionBuilders.weightFactorFunction(1000))
                .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("description", searchContent)),
                        ScoreFunctionBuilders.weightFactorFunction(100));

        // 创建搜索 DSL 查询
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder).build();

        LOGGER.info("\n searchCity(): searchContent [" + searchContent + "] \n DSL  = \n " + searchQuery.getQuery().toString());

        Page<City> searchPageResults = cityRepository.search(searchQuery);
        return searchPageResults.getContent();
    }

}

保存逻辑很简单。

分页 function score query 搜索逻辑如下:

先创建分页参数,然后用 FunctionScoreQueryBuilder 定义 Function Score Query,并设置对应字段的权重分值。城市名称 1000 分,description 100 分。
然后创建该搜索的 DSL 查询,并打印出来。

四、小结

实际场景还会很复杂。这里只是点睛之笔,后续大家优化或者更改下 DSL 语句就可以完成自己想要的搜索规则。

推荐:《Spring Boot 整合 Dubbo/ZooKeeper 详解 SOA 案例
上一篇:《Spring Boot 整合 Mybatis Annotation 注解案例

欢迎扫一扫我的公众号关注 — 及时得到博客订阅哦!
http://www.bysocket.com/
https://github.com/JeffLi1993

Posted in Machine Learning, 技术

带着问题学 Machine Learning:什么是机器学习

机器学习是个难以接受的东西。如果有案例就好了,那就 lets go~

Q:什么是机器学习?

机器学习就是让计算机有像人一样的学习能力的技术,是从数据中寻找有用的知识的数据挖掘技术。
比如呢?运用机器学习技术,类似今日头条给我推我喜欢看的,并看不完的短视频,(害得我卸载了…)。比如说,淘宝知道你喜欢的衣服款式,老是在猜你喜欢那里出现你喜欢的。

Q:那机器学习的数据种类不同吧?

是的,很不一样。根据所学习的数据种类,可以分为监督学习、无监督学习和强化学习等。

Q:什么是监督学习?

监督学习,就是计算机在有结果标记的数据学习后,能预测数据结果的学习过程。
比如,预测数值型数据的回归,预测标称型数据的分类等。太抽象了…
对应的比如,图像处理,垃圾邮件的分类和拦截等

Q:什么是无监督学习?

无监督学习,就是计算机在没有结果标志的数据学习后,能获取有用数据的学习过程。
自然还有个半监督学习,介于两者之间。
比如,预测肿瘤的良性恶性、视频分析等

Q:什么是强化学习?

强化学习,跟无监督学习类似,没有结果标志的数据学习后,又跟监督学习一样,能预测数据结果。
这个’四不像’,被认为人类的主要学习模式之一。
自然也很复杂,涉及到的算法很多。下面聊聊常见的算法。

Q:监督学习和无监督学习中有哪些典型的问题?

在机器学习中有很多典型的问题,比如回归、分类、异常检测、聚类和降维等。自然每个问题,延伸出就是算法,所以也有对应的算法。

Q:什么是回归问题?

回归,都对线性回归有印象吧。回归是数学模型,用于统计的一种方法。是对一组因变量 Yn 和另一组自变量 Xn 之间关系的统计分析。
比如记得以前用 SPSS 的时候,回归统计人的体表面积与身高、体重有关系。从案例看出,回归多半用在监督学习。

Q:什么是分类问题?

分类包括有监督分类和无监督分类。
有监督分类,就是大家一直知道的。术语表达,是指对于指定的模式进行识别的有监督识别问题。这类分类问题,也可以想回归问题那样,被看作是函数近似问题。对,在经过已知样本数据的训练,只能对未知样本估计分类,无法对分类近似分类。
无监督分类,没有任何先验条件,仅仅根据数据,(盲目)的分类。其分类结果肯定是不同纬度的分类,但不能确定分类的类别属性。

Q:什么是异常检测问题?

异常检测,简单说,就是从一堆数据中区分异常值和正常值。术语表达,对数据集中其他项目的项目、事件等识别。比如文本错误问题。

Q:什么是聚类问题?

聚类,和分类问题相似。但属于一种无监督学习。是把相似的样本分成不同的组别或者更多子集。关键词:相似,所以相同组别(子集)的样本具有相似的性质,不同组别(子集)的样本之间具有不同的性质。在聚类问题中,如何计算样本之间的相似度是很重要的。

Q:什么是降维问题?

降维,其目的很直接,提取关键信息。术语表达,是降低样本的个数,得到一组变量的过程。自然,根据样本种类的不同,(我们上面介绍 监督学习 和 无监督学习 ,可以复习下)降维的问题也要分为 监督降维 和 无监督降维。降维有两种方法:特征选择和特征提取。
特征选择,是假定样本数据中包含大量冗余和无关数据,从而找出主要数据的方法。
特征提取,是从高维数据中提取关键信息,转为低维数据进而求解的方法。过程中伴随着除去数据,创建新数据。
广泛用在图像识别领域。

 

Posted in Spring, Spring Boot, 技术

Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!

『 公司需要人、产品、业务和方向,方向又要人、产品、业务和方向,方向… 循环』

本文提纲
一、前言
二、运行 springboot-mybatis-annotation 工程
三、springboot-mybatis-annotation 工程配置详解
四、小结

运行环境:JDK 7 或 8、Maven 3.0+
技术栈:SpringBoot 1.5+、SpringBoot Mybatis Starter 1.2+ 、MyBatis 3.4+

前言

距离第一篇 Spring Boot 系列的博文 3 个月了。《Springboot 整合 Mybatis 的完整 Web 案例》第一篇出来是 XML 配置 SQL 的形式。虽然 XML 形式是我比较推荐的,但是注解形式也是方便的。尤其一些小系统,快速的 CRUD 轻量级的系统。

这里感谢晓春 http://xchunzhao.tk/ 的 Pull Request,提供了 springboot-mybatis-annotation 的实现。

一、运行 springboot-mybatis-annotation 工程

由于这篇文章和 《Springboot 整合 Mybatis 的完整 Web 案例》 类似,所以运行这块环境配置大家参考另外一篇兄弟文章。

然后Application 应用启动类的 main 函数,然后在浏览器访问:

http://localhost:8080/api/city?cityName=温岭市

可以看到返回的 JSON 结果:

{
"id": 1,
"provinceId": 1,
"cityName": "温岭市",
"description": "我的家在温岭。"
}

 

三、springboot-mybatis-annotation 工程配置详解

1.pom 添加 Mybatis 依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>springboot</groupId>
	<artifactId>springboot-mybatis-annotation</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springboot-mybatis-annotation</name>
	<description>Springboot-mybatis :: 整合Mybatis Annotation Demo</description>

	<!-- Spring Boot 启动父依赖 -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.1.RELEASE</version>
	</parent>

	<properties>
		<mybatis-spring-boot>1.2.0</mybatis-spring-boot>
		<mysql-connector>5.1.39</mysql-connector>
	</properties>

	<dependencies>

		<!-- Spring Boot Web 依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- Spring Boot Test 依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- Spring Boot Mybatis 依赖 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>${mybatis-spring-boot}</version>
		</dependency>

		<!-- MySQL 连接驱动依赖 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector}</version>
		</dependency>

		<!-- Junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
	</dependencies>


</project>

2.在 CityDao 城市数据操作层接口类添加注解 @Mapper、@Select 和 @Results

/**
* 城市 DAO 接口类
*
* Created by xchunzhao on 02/05/2017.
*/
@Mapper // 标志为 Mybatis 的 Mapper
public interface CityDao {

/**
* 根据城市名称,查询城市信息
*
* @param cityName 城市名
*/
@Select("SELECT * FROM city")
// 返回 Map 结果集
@Results({
@Result(property = "id", column = "id"),
@Result(property = "provinceId", column = "province_id"),
@Result(property = "cityName", column = "city_name"),
@Result(property = "description", column = "description"),
})
City findByName(@Param("cityName") String cityName);
}

@Mapper 标志接口为 MyBatis Mapper 接口
@Select 是 Select 操作语句
@Results 标志结果集,以及与库表字段的映射关系

其他的注解可以看 org.apache.ibatis.annotations 包提供的,如图:

 

可以 git clone 下载工程 springboot-learning-example ,springboot-mybatis-annotation 工程代码注解很详细。 https://github.com/JeffLi1993/springboot-learning-example

四、小结

注解不涉及到配置,更近贴近 0 配置。再次感谢晓春 http://xchunzhao.tk/ 的 Pull Request~

欢迎扫一扫我的公众号关注 — 及时得到博客订阅哦!
— http://www.bysocket.com/ —
— https://github.com/JeffLi1993 —