Полный пример кода можно найти в личном репозитории GitHub :(github.com/KimZing), Содержит контроллер/репозиторий и тестовый код.
Добро пожаловать, звезда, если есть какие-либо ошибки, добро пожаловать, чтобы исправить_
1. Знакомство с окружающей средой
- idea 2016.3
- jdk 1.8
- ElasticSearch 2.4 (причина, по которой последняя версия не используется, заключается в том, что версии SpringBoot и ES должны совпадать, а SpringBoot Starter в настоящее время не поддерживает последнюю версию)
2. Введение в ЭС
Студенты, разработавшие поиск Java, должны знать поисковую систему lucene, но lucene — это просто поисковая система, такая же, как двигатель автомобиля, который важен, но не может использоваться напрямую. Позже появился известный поиск solr, который предоставлял соответствующий интерфейс веб-операций и работу java API, но параллелизм данных solr и производительность большого объема данных сравнивали с опоздавшим ES. Определенный пробел все же есть, и ES рождается для поддержки распределенных кластеров.
Что такое ЭС? Мы можем сравнить ES с базой данных Mysql, которая также используется для хранения данных, но предоставляет больше функций поиска, чем Mysql, таких как поиск по сегментации слов, поиск по релевантности и т. д., а скорость поиска не того же уровня. ES может достигать скорости запроса миллионов данных в секунду. Далее сравните концепции, используемые в ES с Mysql.
поле | объяснять |
---|---|
index | Индекс эквивалентен библиотеке в Mysql.Например, если есть библиотека под названием «jd», в ней можно создать много таблиц для хранения разных типов данных, а таблица — это тип в ES. |
type | Тип, эквивалентный таблице в Mysql, хранящий данные типа json |
document | Документ, документ эквивалентен строке данных в Mysql. |
shards | Фрагментация в обычном понимании означает, что данные разделены на несколько областей для хранения, что можно понимать как подбазу данных и подтаблицу в mysql (не очень уместно) |
replicas | Резервная копия — это количество резервных копий шардов, что эквивалентно резервной базе данных mysql. |
ES использует данные json для передачи данных, например {username:king,age:12}, тогда все эти данные json являются документом, а имя пользователя и возраст — полями.
3. SpringBoot интегрирует зависимости ES
//ES的核心依赖Starter
compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')
//jna依赖,否则项目启动时,会报classNotFound: native method disable的错误
compile("com.sun.jna:jna:3.0.9")
//添加web支持,方便测试
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
В-четвертых, файл конфигурации
Конфигурационный файл можно настроить или нет.Структура зависимостей data-elasticsearch уже содержит jars Lucene и ES.SpringBoot автоматически сгенерирует для нас репозиторий ES локально, а под проектом будет автоматически сгенерирована папка данных для его хранения , данные ЭС. Если мы не настроим экземпляр ES, Тогда SpringBoot автоматически сгенерирует этот инстанс ES, конечно, производительность точно нехорошая, поэтому мы все равно используем свой инстанс ES.
Структура зависимостей data-elasticsearch
Конфигурация для подключения к отдельному экземпляру ES выглядит следующим образомspring:
data:
#ElasticSearch的连接地址
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: localhost:9300
Для установки ES вы можете обратиться к моему другому сообщению в блоге CentOS6.5 Установка ES учебник
Пять, напишите класс объекта хранения
Следующие три аннотации в основном используются при написании классов сущностей.
1. Аннотация к классу: @Document (эквивалент @Entity/@Table объектов Hibernate) (обязательно)
тип | Имя свойства | По умолчанию | инструкция |
---|---|---|---|
String | indexName | никто | Имя индексной библиотеки, рекомендуется называть ее именем проекта |
String | type | "" | Тип, рекомендуется называть сущность именем сущности |
short | shards | 5 | Количество разделов по умолчанию |
short | replica | 1 | Количество резервных копий по умолчанию на раздел |
String | refreshInterval | "1s" | Интервал обновления |
String | indexStoreType | "fs" | Тип хранения индексного файла |
2. Аннотация первичного ключа: @Id (эквивалентно аннотации @Id первичного ключа сущности Hibernate) (обязательно)
Просто личность, никаких атрибутов.
3. Аннотация свойства @Field (эквивалент аннотации @Column сущности Hibernate)
@Field по умолчанию можно не указывать, и все свойства будут добавлены в ES по умолчанию.
тип | Имя свойства | По умолчанию | инструкция |
---|---|---|---|
FileType | type | FieldType.Auto | Типы свойств определяются автоматически |
FileType | index | FieldIndex.analyzed | Сегментация слов по умолчанию |
boolean | store | false | Исходный текст не сохраняется по умолчанию |
String | searchAnalyzer | "" | Указывает токенизатор для использования при поиске в поле |
String | indexAnalyzer | "" | Токенизатор, указанный при индексации указанного поля |
String[] | ignoreFields | {} | Если поле нужно игнорировать |
4. Пример класса сущностей
@Data //lombok注解,会自动生成setter/getter,需要引入lombok的包才能使用。
@Document(indexName = "shop", type = "user", refreshInterval = "0s")
public class User {
@Id
private Long id;
private String username;
private String realname;
private String password;
private Integer age;
//这三个注解是为了前台序列化java8 LocalDateTime使用的,需要引入jsr310的包才可以使用
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime birth;
}
Шесть, напишите склад
1. Написание кода
Чтобы написать класс, который наследует ElasticsearchRepository
/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/11/27 下午10:10
* @desc 用户仓库.
*/
public interface UserRepository extends ElasticsearchRepository<User, Long>{
}
Давайте взглянем на структуру наследования ElasticsearchRepository (ниже), на самом деле мы можем обнаружить, что это все еще набор репозиториев JPA, тогда мы можем фактически использовать набор интерфейсных операций JPA для добавления, удаления, изменения и проверить данные. Spring автоматически сгенерирует соответствующие прокси-классы в соответствии с именами методов для реализации этих методов.
2. Основные операции CRUD
Давайте взглянем на некоторые из основных методов, которые реализованы в ElasticsearchRepository. Имена этих методов были хорошо объяснены, так что вы можете убедиться сами, их легко понять.
3. Немного сложная операция
Эти методы, поставляемые с jpa, конечно, не могут удовлетворить потребности нашего бизнеса, так как же нам настроить эти методы? Пока мы используем определенное слово для определения имени метода, Spring будет анализировать имя метода, которое мы написали, Генерировать соответствующие экземпляры для обработки данных, легко ли это? Затем используйте примеры из официальной документации Spring для демонстрации.
Сначала посмотрите на описание ключевых слов.
ключевые слова | Пример использования | ES-запрос эквивалентен |
---|---|---|
And | findByNameAndPrice | {"bool" : {"должен" : [ {"поле" : {"имя" : "?"}}, {"поле" : {"цена" : "?"}} ]}} |
Or | findByNameOrPrice | {"bool" : {"следует" : [ {"поле" : {"имя" : "?"}}, {"поле" : {"цена" : "?"}} ]}} |
Is | findByName | {"bool" : {"должен" : {"поле" : {"имя" : "?"}}}} |
Not | findByNameNot | {"bool" : {"must_not" : {"поле" : {"имя" : "?"}}}} |
Between | findByPriceBetween | {"bool" : {"должен" : {"диапазон" : {"цена" : {"от" : ?,"до" : ?,"include_lower" : true,"include_upper" : true}}}}} |
LessThanEqual | findByPriceLessThan | {"bool" : {"должен" : {"диапазон" : {"цена" : {"от" : ноль, "до" : ?, "include_lower" : истина, "include_upper" : истина}}}}} |
GreaterThanEqual | findByPriceGreaterThan | {"bool" : {"должен" : {"диапазон" : {"цена" : {"от" : ?, "до" : ноль, "include_lower" : правда, "include_upper" : правда}}}}} |
Before | findByPriceBefore | {"bool" : {"должен" : {"диапазон" : {"цена" : {"от" : ноль, "до" : ?, "include_lower" : истина, "include_upper" : истина}}}}} |
After | findByPriceAfter | {"bool" : {"должен" : {"диапазон" : {"цена" : {"от" : ?, "до" : ноль, "include_lower" : правда, "include_upper" : правда}}}}} |
Like | findByNameLike | {"bool" : {"должен" : {"поле" : {"имя" : {"запрос" : "?*","analyze_wildcard" : правда}}}}} |
StartingWith | findByNameStartingWith | {"bool" : {"должен" : {"поле" : {"имя" : {"запрос" : "?*","analyze_wildcard" : true}}}}} |
EndingWith | findByNameEndingWith | {"bool" : {"должен" : {"поле" : {"имя" : {"запрос" : "*?", "analyze_wildcard" : правда}}}}} |
Contains/Containing | findByNameContaining | {"bool" : {"должен" : {"поле" : {"имя" : {"запрос" : "?", "analyze_wildcard" : правда}}}}} |
In | findByNameIn(Collectionnames) | {"bool" : {"должен" : {"bool" : {"должен" : [ {"поле" : {"имя" : "?"}}, {"поле" : {"имя" : "?" }} ]}}}} |
NotIn | findByNameNotIn(Collectionnames) | {"bool" : {"must_not": {"bool" : {"следует" : {"поле" : {"имя" : "?"}}}}}} |
True | findByAvailableTrue | {"bool" : {"должен" : {"поле" : {"доступно" : true}}}} |
False | findByAvailableFalse | {"bool" : {"должен" : {"поле" : {"доступно" : false}}}} |
OrderBy | findByAvailableTrueOrderByNameDesc | {"sort" : [{ "name" : {"order" : "desc"} }], "bool" : {"must" : {"поле" : {"доступно" : true}}}} |
Давайте напишем несколько примеров для демонстрации. Перечислен только слой хранилища. Работа в целом проверена, проблем нет. Если вам нужен общий код, перейдите в репозиторий github в верхней части этой статьи.
/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/11/27 下午10:10
* @desc 用户仓库.
*/
public interface UserRepository extends ElasticsearchRepository<User, Long>{
/**
* 查询用户名为username的用户
* @param username
* @return
*/
List<User> findByUsername(String username);
/**
* 查询用户名为username并且真实姓名为realname的用户
* @param username
* @param realname
*/
List<User> findByUsernameAndRealname(String username, String realname);
/**
* 查询用户名为username或者姓名为realname的用户
*/
List<User> findByUsernameOrRealname(String username, String realname);
/**
* 查询用户名不是username的所有用户
* @param username
* @return
*/
List<User> findByUsernameNot(String username);
/**
* 查询年龄段为ageFrom到ageTo的用户
* @param ageFrom
* @param ageTo
* @return
*/
List<User> findByAgeBetween(Integer ageFrom, Integer ageTo);
/**
* 查询生日小于birthTo的用户
*/
List<User> findByBirthLessThan(LocalDateTime birthTo);
/**
* 查询生日段大于birthFrom的用户
* @param birthFrom
* @return
*/
List<User> findByBirthGreaterThan(LocalDateTime birthFrom);
/**
* 查询年龄小于或等于ageTo的用户
*/
List<User> findByAgeBefore(Integer ageTo);
/**
* 查询年龄大于或等于ageFrom的用户
* @param ageFrom
* @return
*/
List<User> findByAgeAfter(Integer ageFrom);
/**
* 用户名模糊查询
* @param username
* @return
*/
List<User> findByUsernameLike(String username);
/**
* 查询以start开头的用户
* @param start
* @return
*/
List<User> findByUsernameStartingWith(String start);
/**
* 查询以end结尾的用户
* @return
*/
List<User> findByUsernameEndingWith(String end);
/**
* 查询用户名包含word的用户
* @param word
* @return
*/
List<User> findByUsernameContaining(String word);
/**
* 查询名字属于usernames中的用户
* @param usernames
* @return
*/
List<User> findByUsernameIn(Collection<String> usernames);
/**
* 查询名字不属于usernames中的用户
* @param usernames
* @return
*/
List<User> findByUsernameNotIn(Collection<String> usernames);
/**
*最后来个复杂点的:查询年龄小于ageTo,姓名以start开头,id大于idTo的用户,并且按照年龄倒序
* @return
*/
List<User> findByAgeBeforeAndUsernameStartingWithAndIdGreaterThanOrderByAgeDesc(Integer ageTo, String start, Long idTo);
}
4. Более сложные операции
Мы можем использовать аннотацию @Query для запроса, что требует от нас написания операторов запроса ES самостоятельно, и нам нужно знать запросы ES, На самом деле это очень просто. Взгляните на официальный пример
public interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("{\"bool\" : {\"must\" : {\"field\" : {\"name\" : \"?0\"}}}}")
Page<Book> findByName(String name,Pageable pageable);
}
5. Мы также можем запросить по аналогии с критериями в Hibernate,
На данный момент нам нужно самим написать условия запроса, внедрить UserRepository в класс, использовать метод поиска для передачи параметров запроса, а затем получить результаты запроса. Пример выглядит следующим образом:
/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/11/28 下午12:53
* @desc 用户服务.
*/
@Service
public class UserService {
@Resource
UserRepository userRepository;
public Page<User> getUsers() {
//创建builder
BoolQueryBuilder builder = QueryBuilders.boolQuery();
//builder下有must、should以及mustNot 相当于sql中的and、or以及not
//设置模糊搜索,真实姓名中包含金的用户
builder.must(QueryBuilders.fuzzyQuery("realname", "金"));
//设置用户名为king
builder.must(new QueryStringQueryBuilder("king").field("username"));
//排序
FieldSortBuilder sort = SortBuilders.fieldSort("age").order(SortOrder.DESC);
//设置分页
//====注意!es的分页和Hibernate一样api是从第0页开始的=========
PageRequest page = new PageRequest(0, 2);
//构建查询
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
//将搜索条件设置到构建中
nativeSearchQueryBuilder.withQuery(builder);
//将分页设置到构建中
nativeSearchQueryBuilder.withPageable(page);
//将排序设置到构建中
nativeSearchQueryBuilder.withSort(sort);
//生产NativeSearchQuery
NativeSearchQuery query = nativeSearchQueryBuilder.build();
//执行,返回包装结果的分页
Page<User> resutlList = userRepository.search(query);
return resutlList;
}
}
Автор: Ким Зинг Источник: ЦСДН оригинал:blog.CSDN.net/king boy W или останься…