Prefacio
En el artículo anterior, SpringBoot, MyBatis, Druid y Pagehelper se integraron y se implementaron operaciones de múltiples fuentes de datos. Este artículo presenta y utiliza principalmente ElastISearch, el motor de búsqueda más popular, y lo usa en combinación con SpringBoot.
Introducción a elasticsearch
Elasticsearch es un servidor de búsqueda basado en Lucene. En realidad, encapsula Lucene y proporciona la interfaz de operación de la API REST. Elasticsearch es un motor de búsqueda y análisis de texto completo de código abierto altamente escalable que se puede utilizar para almacenar, buscar y analizar Big Data.
Las principales características de Elasticsearch: distribuida, alta disponibilidad, escritura asincrónica, multi-API, orientado a documentos.
Conceptos básicos de ElasticSearch: Cerca de tiempo real, clúster, nodo (guardar datos), índice, fragmento (fragmentos de índice de corte), réplicas (la corte puede establecer múltiples réplicas). Puede almacenar, buscar y analizar rápidamente cantidades masivas de datos.
Casos de uso de Elasticsearch: Wikipedia, Overflow de Stack, Github, etc.
SpringBoot integra elasticsearch
Antes de usar SpringBoot para integrar ElasticSearch, debemos comprender la relación entre ellos.
| Versión de arranque de primavera (x) | Spring Data Elasticsearch Version (Y) | Versión de ElasticSearch (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 ** |
La versión de SpringBoot que estamos usando aquí es 1.5.9, y la versión de Elasticsearch es 2.3.5.
Utilizando SpringBoot para integrar ElasticSearch, generalmente se encapsula usando SpringData, y luego la interfaz de la capa DAO hereda la clase ElasticSearchRepository. Esta clase implementa muchos métodos, como el método CRUD comúnmente utilizado.
Uso de SpringData
Primero, haga preparativos relevantes antes de su uso.
La configuración de Maven es la siguiente:
<Spendency> <MoupRoupId> org.springframework.boot </groupid> <artifactid> spring-boot-starter-web </artifactid> <version> 1.5.9.release </versión> </pendency> <epardency> <proupid> org.springfframe.boot </groupid> <artifactid> spring-boot-shate-data-data-dataid-dataidsear <Versión> 1.5.9.Release </versión> </pendency>
Configuración de la aplicación. Properties
spring.data.elasticsearch.repositories.enabled = truespring.data.elasticsearch.cluster-nodes = 127.0.0.1/: 9300
Nota: 9300 es el puerto del cliente Java. 9200 es una interfaz que admite HTTP RESTful.
Más configuraciones:
Spring.Data.elasticsearch.cluster-Name Elasticsearch Nombre del clúster. (Predeterminado: Elasticsearch)
Spring.Data.elasticsearch.Cluster-Nodes Lista de direcciones de nodo de clúster, separadas por comas. Si no se especifica, inicie un nodo cliente.
Spring.Data.elasticsearch.Propertie se utiliza para configurar propiedades adicionales del cliente.
Spring.Data.elasticsearch.Repositories.Enabled Habilitar el repositorio de ElasticSearch. (Predeterminado: verdadero).
Redacción de código
Clase de entidad
@Document (indexname = "userIndex", type = "user") La clase pública usuarios implementa serializable { / ** * * / private static final long SerialVersionUid = 1l; / ** Número*/ ID de largo privado; / ** Nombre*/ Nombre de cadena privada; / ** edad*/ edad privada entera; / ** Descripción*/ Descripción de la cadena privada; / ** Tiempo de creación*/ String private Createtm; // getter y setter omitido}Al usar SpringData, debe establecer IndexName y escribir en la clase de entidad. Si se compara con las bases de datos tradicionales, es equivalente a bibliotecas y tablas.
¡Cabe señalar que tanto IndexName como Type deben estar en minúsculas!
Capa de dao
La interfaz pública userdao extiende ElasticSearchRepository <User, Long> {}La capa DAO es relativamente simple aquí, solo herede la clase ElasticsearchRepository. Los métodos principales son guardar, eliminar y buscar. El método Guardar es como insertar y actualizar. Si no hay, se agregará y si hay uno, se cubrirá. El método Eliminar es principalmente para eliminar los datos y las bibliotecas de índice. En cuanto a la búsqueda, es una consulta, incluidas algunas consultas de uso común, como paginación, pesas, etc.
Capa de servicio
@ServicePublic UserServiceImpl implementa UserService {@aUtowired userdao userDao; @Override public boolean Insert (usuario de usuario) {boolean falg = false; intente {userDao.save (usuario); falg = verdadero; } catch (Exception e) {E.PrintStackTrace (); } return falg; } @Override Public List <Serer> Search (String SearchContent) {QueryStringQueryBuilder Builder = new QueryStringQueryBuilder (SearchContent); System.out.println ("Declaración de consulta:"+Builder); ITerable <Usser> SearchResult = UserDao.Search (Builder); Iterator <Ser User> iterator = SearchResult.Iterator (); List <serer> list = new ArrayList <Serer> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } Lista de retorno; } @Override Public List <Serem> SearchUser (Integer PageNumber, Integer PageSize, String SearchContent) {// Parámetros de paginación pagables pagables = new Pagequest (PageNumber, PageSize); QueryStringQueryBuilder Builder = new QueryStringQueryBuilder (SearchContent); SearchQuery SearchQuery = New NatesearchQueryBuilder (). Withpagable (pagible) .withQuery (constructor) .build (); System.out.println ("Declaración de consulta:" + SearchQuery.getQuery (). ToString ()); Página <Serem> SearchPageSults = UserDao.Search (SearchQuery); return searchPageResults.getContent (); } @Override public List<User> searchUserByWeight(String searchContent) { // Query according to weights FunctionScoreQuiller functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() .add(QueryBuilders.boolQuery(). should(QueryBuilders.matchQuery("name", searchContent)), ScoreFunctionBuilders.WeightFactorFunction (10)) .Add (QueryBuilders.BoolQuery (). Debería (QueryBuilders.MatchQuery ("Descripción", SearchContent)), ScoreFunctionBuilders.WeightFactorFunction (100)). Setminscore (2); System.out.println ("Declaración de consulta:" + functionsCoreQueryBuilder.ToString ()); ITerable <Serem> SearchResult = UserDao.Search (functionsCoreQueryBuilder); Iterator <Ser User> iterator = SearchResult.Iterator (); List <serer> list = new ArrayList <Serer> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } Lista de retorno; }}Aquí simplemente he escrito varios métodos, el método principal es la consulta. Las consultas incluyen búsqueda de texto completo, consulta de paginación y consulta de peso. Lo que debe explicarse es la consulta de peso. Cuanto mayor sea el puntaje de peso, mayor será el resultado de la consulta. Si no se establece una puntuación para otros datos, su puntaje predeterminado es 1. Si no desea consultar estas declaraciones, solo use SetMinscore para establecerlo en más de 1.
Prueba de código
Llame a la interfaz para agregar datos
Nuevos datos:
Post http: // localhost: 8086/api/user {"id": 1, "nombre": "zhang san", "edad": 20, "descripción": "zhang san es un ingeniero de desarrollo java", "creattm": "2018-4-25 11:07:42"} {"id": 2, "nombre": "li si", "edad": ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",". es un ingeniero de pruebas "," CreateTM ":" 1980-2-15 19:01:32 "} {" id ": 3," Nombre ":" Wang Wu "," Age ": 25," Descripción ":" Wang Wu es un ingeniero de operación y mantenimiento "," Createtm ":" 2016-8-21 06:11:32 "}} Realizar consultas de texto completo
preguntar
http: // localhost: 8086/api/user? SearchContent = Ingeniero
devolver
[{"id": 2, "nombre": "li si", "edad": 14, "descripción": "li si es un ingeniero de prueba", "creattm": "1980-2-15 19:01:32"}, {"id": 1, "nombre": "zhang san", "edad": 20, "descripción": "Zhang San es un ingeniero de desarrollo de Java", "create": "2018". 11:07:42 "}, {" id ": 3," Nombre ":" Wang Wu "," Age ": 25," Descripción ":" Wang Wu es un ingeniero de operación y mantenimiento "," CreateTM ":" 2016-8-21 06:11:32 "}] Realizar una consulta de paginación
preguntar
http: // localhost: 8086/api/user? Pagenumber = 0 & PageSize = 2 & SearchContent = Engineer
devolver
[{"id": 2, "nombre": "li si", "edad": 14, "descripción": "li si es un ingeniero de prueba"}, {"id": 1, "nombre": "zhang san", "edad": 20, "descripción": "zhang san es un ingeniero de desarrollo de java"}] Realizar una consulta de peso
preguntar
http: // localhost: 8086/API/user2? SearchContent = Li SI
devolver
[{"id": 2, "nombre": "li si", "edad": 24, "descripción": "li si es ingeniero de pruebas", "createtm": "1980-2-15 19:01:32"}]La declaración de impresión de la consulta de peso:
Declaración de consulta: {{"function_score": {"funciones": [{"filtro": {"bool": {"bool": {"debería": {"coincidir: {" nombre ": {" consulta ":" li si "," tipo ":" boolean "}}}}}}}}}}}}}}}}}}}}:" peso ": 10 {0 {" " "bool": {"debería": {"coincidir": {"descripción": {"consulta": "li si", "tipo": "boolean"}}}}}}, "peso": 100.0}], "min_score": 2.0}}}}}}}}}Nota: En la prueba, dado que el peso mínimo de SetMinscore se dividirá en 2, no se mostrarán datos irrelevantes. Si desea mostrarlo, simplemente elimínelo en el código.
Después de agregar nuevos datos, puede ingresar: http: // localhost: 9200/_plugin/head/en el navegador
Luego haga clic en la consulta básica para ver los datos agregados. Si desea usar la consulta de instrucciones, ¡puede pegar la instrucción de consulta impresa por la consola en el programa a la interfaz de consulta para la consulta!
Nota: Instalé ElasticSearch aquí en Windows e instalé el cabezal del complemento ES. Los pasos de instalación específicos están al final del artículo.
Además de SpringData, en realidad hay otros métodos para operar Elasticsearch.
Por ejemplo, use la API de Elasticsearch nativa y use la clase TransportClient para implementarla.
O úselo para encapsular por primavera, solo inyecte el frijol en la capa de servicio.
Ejemplo:
@AUTOWIREDEDIRDEDECHTemplate ElasticsearchTemplate;
Sin embargo, los métodos anteriores tienen sus limitaciones, es decir, a medida que se cambia la versión de ElasticSearch, la API Java relevante también se ajusta constantemente, es decir, después de que se cambia la versión del servidor de Elasticsearch, el código del cliente puede necesitar ser redactado.
Por lo tanto, introduce una herramienta de terceros muy útil JestClient. Encapsula Elasticsearch y llena el vacío en el cliente de interfaz Elasticsearch Httprest. Es adecuado para las versiones de ElasticSearch 2.x o arriba, y no hay necesidad de cambiar el código debido al cambio de versión del servidor Elasticsearch.
Jestclient
Primero agregue las siguientes dependencias en Maven:
<Spendency> <ProupId> io.searchbox </proupid> <artifactid> jest </arfactid> <versión> 5.3.3 </versión> </dependencia>
Luego escriba el código de prueba relevante.
Los comentarios en el código deberían ser muy completos, por lo que no hablaré demasiado sobre el código aquí.
import java.util.arrayList; import java.util.list; import org.elasticsearch.index.Query.QueryBuilders; import org.elasticsearch.search.builder.searchsourceBuilder; import Com.pancm.pojo.user; import io.searchbox.client.jestclient; import io.searchbox.client.JestClientFactory; import io.searchbox.client.jestresult; import io.searchbox.client.config.httpclientconfig; import io.searchbox.core.bulk; import io.searchbox.core.bulkresult; import io.searchbox.core.deletet; import io.searchbox.core.documentResult; import io.searchbox.core.index; import io.searchbox.core.search; import io.searchbox.indices.createindex; import io.searchbox.Indices.deleteindex; import io.searchbox.indeices.mapping; import iO.SearchBox.Indices.Mapping; JestTest {JestClient de JestClient estático privado; String static privado indexName = "UserIndex"; // cadena estática privada indexName = "userIndex2"; cadena estática privada typename = "usuario"; String static privado elasticips = "http://192.169.2.98:9200"; // string static private elasticips = "http://127.0.0.1:9200"; public static void main (string [] args) lanza la excepción {jestClient = getJestClient (); insertBatch (); Serach1 (); Serach2 (); Serach3 (); jestClient.close (); } private static jestClient getJestClient () {jestClientFactory factory = new JestClientFactory (); factory.sethttpClientConfig (new httpClientConfig.Builder (elasticips) .conntimeout (60000) .ReadTimeOut (60000) .multithreaded (true) .build ()); return factory.getObject (); } public static void insertBatch () {list <S Object> objs = new ArrayList <ject> (); objs.Add (nuevo usuario (1L, "Zhang San", 20, "Zhang San es ingeniero de desarrollo de Java", "2018-4-25 11:07:42"); objs.Add (nuevo usuario (2l, "Li Si", 24, "Li Si es ingeniero de pruebas", "1980-2-15 19:01:32"); objs.Add (nuevo usuario (3L, "Wang Wu", 25, "Wang Wu es ingeniero de operación y mantenimiento", "2016-8-21 06:11:32"); resultado booleano = falso; intente {resultado = insertBatch (jestClient, indexName, typename, objs); } catch (Exception e) {E.PrintStackTrace (); } System.out.println ("lote nuevo:"+resultado); } / *** Búsqueda de texto completo* / public static void Serach1 () {String Query = "Ingeniero"; intente {SearchSourceBuilder SearchSourceBuilder = new SearchSourceBuilder (); SearchSourceBuilder.Query (QueryBuilders.queryStringQuery (consulta)); // Configuración de página SearchSourceBuilder.From (0) .size (2); System.out.println ("Declaración de consulta de búsqueda de texto completo:"+SearchSourceBuilder.ToString ()); System.out.println ("La búsqueda de texto completo devuelve el resultado:"+Search (JestClient, IndexName, Typename, SearchSourceBuilder.ToString ())); } catch (Exception e) {E.PrintStackTrace (); }} / *** Search exacta* / public static void serach2 () {try {SearchSourceBuilder SearchSourceBuilder = New SearchSourceBuilder (); SearchSourceBuilder.Query (QueryBuilders.MermQuery ("Age", 24)); System.out.println ("Declaración de consulta de búsqueda exacta:"+SearchSourceBuilder.ToString ()); System.out.println ("La búsqueda exacta devuelve el resultado:"+Search (JestClient, IndexName, Typename, SearchSourceBuilder.ToString ())); } catch (Exception e) {E.PrintStackTrace (); }} / *** Búsqueda de intervalo* / public static void serach3 () {string createTm = "createTm"; Cadena de = "2016-8-21 06:11:32"; Cadena a = "2018-8-21 06:11:32"; intente {SearchSourceBuilder SearchSourceBuilder = new SearchSourceBuilder (); SearchSourceBuilder.Query (QueryBuilders.RangeQuery (CreateTM) .gte (from) .lte (a)); System.out.println ("Declaración de búsqueda de intervalo:"+SearchSourceBuilder.ToString ()); System.out.println ("Interval Search devuelve el resultado:"+Search (JestClient, IndexName, Typename, SearchSourceBuilder.ToString ())); } catch (Exception e) {E.PrintStackTrace (); }} / ** * Crear índice * @param indexname * @return * @throws excepción * / public boolean createIndex (jestClient JestClient, String indexName) lanza la excepción {jestresult jr = jestClient.ExeCute (newIndex.builder (indexName) .BuLild ()); return jr.issucEceded (); } / ** * Nuevos datos * @param indexName * @param typename * @param fuente * @return * @throws excepción * / public boolean inser. Jestresult jr = jestClient.Execute (PutMapping); return jr.issucEceded (); } / ** * Datos de consulta * @param indexName * @param typename * @return * @throws excepción * / public static string getIndexMapping (jestClient jestClient, string indexName, string typename) lanza excepción {getMapping getMapping = new GetMapping.Builder (). AddEx (indexName) .addtype (typeLy ().). Jestresult jr = jestClient.Execute (getMapping); return jr.getJSonstring (); } / ** * Agregue datos en lotes * @param indexname * @param typename * @param objs * @return * @throws excepción * / public static boolean insertBatch (jestclient jestclient, string indexName, string typename, list <bect> objs) arroja excepción {bulk.builder = new New New Bulk.builder (). DefaultIndex (indexName) .DefaultType (typename); for (object obj: objs) {index index = new index.builder (obj) .Build (); bulk.addaction (índice); } BulkResult br = jestClient.Execute (bulk.build ()); return br.issucCeded (); } / ** * Búsqueda de texto completo * @param indexName * @param typename * @param consulty * @return * @throws excepción * / public static string string (jestClient jestClient, string indexName, string typename, string (consulta) lanza la excepción {búsqueda de búsqueda = nueva búsqueda. Jestresult jr = jestClient.Execute (búsqueda); // system.out.println ("-"+jr.getjSonstring ()); // system.out.println ("-"+jr.getSourceasObject (user.class)); return jr.getSourCeASString (); } / ** * Eliminar índice * @param indexname * @return * @throws excepción * / public boolean delete (jestClient JestClient, String indexName) lanza la excepción {jestresult jr = jestClient.Execute (new Delete.builder (indexName) .build ()); return jr.issucEceded (); } / ** * Eliminar datos * @param indexname * @param typename * @param id * @return * @throws excepción * / public boolean delete (jestClient JestClient, string indexName, string typename, string id) lanza excepción {documentResult dr = jestClient.execute (newe Delete.builder (id) .index (indexName) .type (typename) .Build ()); regresar Dr.IssucCeded (); }Nota: Antes de las pruebas, primero expliquemos que la versión Elasticsearch instalada en el sistema Windows local es 2.3.5, y la versión Elasticsearch instalada en el servidor Linux es 6.2.
Resultados de las pruebas
Búsqueda de texto completo
Declaración de consulta de búsqueda de texto completo: {"from": 0, "tamaño": 2, "consulta": {"query_string": {"consulta": "ingeniero"}}} la búsqueda de texto completo devuelve el resultado: {"id": 1, "nombre": "zhang san", "edad": 20, "descripción": "Zhang san es un ingeniero de desarrollo java", "createtm": "createtm" 11:07:42 "}, {" id ": 2," Nombre ":" Li si "," Age ": 24," Descripción ":" Li si es ingeniero de pruebas "," Createtm ":" 1980-2-15 19:01:32 "}Búsqueda de coincidencias
Declaración de consulta de búsqueda precisa: {"consulta": {"término": {"edad": 24}}} La búsqueda precisa devuelve el resultado: {"id": 2, "nombre": "li si", "edad": 24, "descripción": "li si es un ingeniero de prueba", "creatm": "1980-2-15 19:01:32"}}Búsqueda de intervalo de tiempo
Declaración de búsqueda de intervalo: {"Query": {"rango": {"CreateTm": {"de": "2016-8-21 06:11:32", "a": "2018-8-21 06:11:32", "include_lower": true, "include_upper": true}}}} Resultado de la búsqueda de interval San "," Age ": 20," Descripción ":" Zhang San es ingeniero de desarrollo de Java "," CreateTM ":" 2018-4-25 11:07:42 "}Después de agregar nuevos datos, podemos ir a Linux Kibana para realizar consultas relacionadas, y los resultados de la consulta son los siguientes:
NOTA: Kibana es un software de código abierto en Elk. Kibana proporciona interfaces web amigables para el análisis de registros para Logstash y Elasticsearch para ayudar a resumir, analizar y buscar registros de datos importantes.
Los resultados devueltos por la prueba en el código anterior están en línea con nuestras expectativas. Entre ellos, solo se usa una pequeña parte de JestClient. Para obtener más uso, puede consultar la documentación oficial de JestClient.
Instale Elasticsearch en Windows
1. Preparación de documentos
Descargar dirección: https://www.elastic.co/downloads
Seleccione la versión relacionada con ElasticSearch, luego seleccione el archivo zip de nombre de sufijo para descargar, y luego descompite después de la descarga.
2. Inicie Elasticsearch
Vaya al directorio bin y ejecute elasticsearch.bat
Luego ingrese: Localhost: 9200 en la navegación
¡Mostrar con éxito la interfaz significa éxito!
3. Instale el complemento de ES
Instalación del cabezal de la interfaz de administración web
Ingrese el directorio bin, abra CMD e ingrese la interfaz DOS
Ingrese: plugin install mobz/elasticsearch-head
Hacer una descarga
Después de la descarga exitosa, ingrese: http: // localhost: 9200/_plugin/head/
Si se muestra la interfaz, ¡la instalación tendrá éxito!
4. Registre el servicio
Ingrese el directorio bin, abra CMD e ingrese la interfaz DOS
Ingresar:
Service.Bat InstallService.Bat Start
Después del éxito, ingrese
servicios.msc
¡Salte a la interfaz de servicio de servicio para ver el estado de ejecución de ES directamente!
otro
Dirección de API del sitio web oficial de ElasticSearch:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.3/index.html
JestClientGithub Dirección:
https://github.com/searchbox-io/jest (descarga local)
Puse el proyecto en Github.
https://github.com/xuwujing/springboot (descarga local)
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.