Cet article n'implique pas les principes spécifiques d'Elasticsearch, mais enregistre uniquement comment importer rapidement des données dans MySQL pour la recherche en texte intégral.
Au travail, vous devez implémenter une fonction de recherche et importer des données de base de données existantes. Le chef d'équipe recommande d'utiliser Elasticsearch pour l'implémenter. Vous pouvez rechercher par le biais de tutoriels en ligne, qui sont des articles relativement anciens. Je n'ai pas d'autre choix que de l'explorer moi-même. Reportez-vous à la documentation ES et enfin créez le service. Je vais l'enregistrer. J'espère que les amis ayant les mêmes besoins peuvent éviter les détours et pourront rapidement construire un service Elasticsearch disponible en fonction de ce tutoriel.
ES Construction
Les builds ES peuvent télécharger directement des fichiers ZIP et des conteneurs Docker. Relativement parlant, Docker est plus adapté à ce que nous exécutons des services. Il est possible de construire facilement un cluster ou de créer un environnement de test. La méthode du conteneur est également utilisée ici. Tout d'abord, nous avons besoin d'un dockerfile:
De docker.elastic.co/elasticsearch/Elasticsearch-oss:6.0.0# La configuration de soumission inclut le nouveau elasticsearch.yml et keystore.jks files copy --chown = elasticsearch: elasticsearch conf / / usr / share / elasticsearch / config / # install ikrun ./bin/elasticsearch-plugin install install install install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip# install wearonlyrestrun ./bin/elasticsearch-plugin instally https://github.com/hyy-yu/beziercurvemo/raw/master/readonlyrest-1.16.14_es6.0.0.zipuser elasticsearchcmd ./bin/ElasticSearch
Voici une explication de l'opération ci-dessus:
Configuration édictique elasticsearch.yml
cluster.name: "docker-cluster" Network.host: 0.0.0.0 # minimum_master_nodes doit être explicitement défini lorsqu'il est lié sur une IP publique # définie sur 1 pour autoriser les clusters de nœuds # Détails: https://github.com/elastic/elasticsearch/pull/17288discovery.zen.Minimum_master_Nodes: 1 # pour l'échange.zen.Minimum_Master_Nodes: 1 # pour l'échange.zen.Minimum_master_Nodes: 1 # pour l'échange.zen.Minimum_master_Nodes: 1 # pour l'échange.zen.Minimum_Master_Nodes: 1 # pour le système sur ES bootstrap.memory_lock: true http.type: ssl_netty4readonlyrest: activer: true ssl: activer: true keystore_file: "server.jks" keystore_pass: serveur key_pass: server Access_Control_rules: "Nom:" Block 1 - Root "Type: Autoriser les groupes: [" "" ["utilisateur"] Indices: ["" papier * "] Actions: [" Indices: données / lecture / * "] Utilisateurs: - Nom d'utilisateur: root auth_key_sha256: cb7c98bae153065db931980a13bd45ee3a77cb8f27a7dfee68f6863777ACC xiaoMing Auth_Key: XiaoMing: xiaoMing Group: ["User"]
Ici bootstrap.memory_lock: true est une fosse, interdisant l'échange de mémoire. Le document a déjà expliqué que certains OS échangeront une mémoire temporairement inutilisée dans une zone du disque dur pendant l'exécution. Cependant, ce comportement augmentera le taux d'utilisation des ressources des ES et rendra même le système incapable de répondre.
Il est déjà évident dans le fichier de configuration qu'un utilisateur racine appartient au groupe d'administration et que l'administrateur a toutes les autorisations. Parce que XiaoMing est dans le groupe d'utilisateurs, il ne peut accéder à l'index du papier et ne peut lire que, mais ne peut pas fonctionner. Pour une configuration plus détaillée, veuillez consulter: la documentation ReadOnlyRest
À ce stade, les préparatifs d'ES ont été achevés. Docker build -t esimage: tag. Docker Run -P 9200: 9200 ESIMAGE: TAG RUN.
Si https://127.0.0.1:9200/ revient
{"name": "vakwrir", "cluster_name": "docker-cluster", "cluster_uuid": "ysydowkvrh2swz907s2m_w", "version": {"numéro": "6.0.0", "build_hash": "8f0685b", "build_date":: "2017-11-10t18: 41: 22.859z", "build_snapshot": false, "lunene_version": "7.0.1", "minimum_wire_compatibilité_version": "5.6.0", "minimum_index_compatibilité_Le protagoniste de notre tutoriel est apparu. Je partagerai plusieurs API couramment utilisées pour taquiner et déboguer:
{{URL}} est remplacé par votre adresse ES locale.
Importer des données MySQL
J'utilise les données MySQL ici, mais en fait, d'autres bases de données sont les mêmes. La clé est de savoir comment importer. Le tutoriel en ligne recommandera le plug-in MySQL pour Logstash, Beat et ES pour l'importation. Je l'ai également essayé. La configuration est lourde et les documents sont rares. Si la structure de la base de données est un peu compliquée, l'importation est une tâche laborieuse, elle n'est donc pas recommandée. En fait, ES dispose de bibliothèques API correspondantes dans chaque langue. Vous pouvez assembler les données dans JSON au niveau de la langue et les envoyer à ES via la bibliothèque API. Le processus est à peu près comme suit:
J'utilise l'élastique de la bibliothèque ES de Golang. Vous pouvez rechercher sur GitHub d'autres langues, et la méthode de fonctionnement est la même.
Ensuite, utilisez une base de données simple pour l'introduire:
Table de papier
| identifiant | nom |
|---|---|
| 1 | Simulation de l'école primaire n ° 1 de Pékin |
| 2 | Jiangxi Beijing General College Entrance Examination Questions |
Table de province
| identifiant | nom |
|---|---|
| 1 | Pékin |
| 2 | Jiangxi |
Table de papier
| Paper_id | province_id |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
Comme mentionné ci-dessus, le papier et la province sont des relations de plusieurs à plusieurs. Maintenant que les données papier sont entrées dans ES, vous pouvez rechercher flou par le nom du papier ou filtrer dans la province. Le format de données JSON est le suivant:
{"id": 1, "nom": "Beijing n ° 1 Volume de simulation de l'école primaire", "Provinces": [{"id": 1, "nom": "Beijing"}]} Préparez d'abord un fichier mapping.json, qui est la définition de la structure de stockage des données dans ES.
{"mappings": {"docs": {"include_in_all": false, "Properties": {"id": {"type": "long"}, "name": {"type": "text", "analyzer": "ik_max_word" // utilise le plus grand parterator}, "province": {"type": "net "id": {"type": "entier"}, "name": {"type": "text", "index": "false" // non indexé}}}}}}}}}}}}}, "paramètres": {"numéro_of_shards": 1, "nombre_of_repllicas": 0}}Il convient de noter que le champ _ALL est annulé. Cette valeur par défaut collectera tous les champs de stockage pour réaliser une recherche restreinte inconditionnelle. L'inconvénient est que l'espace occupe beaucoup.
J'ai défini le numéro de fragment sur 1 et aucune réplique n'est définie. Après tout, ce n'est pas un cluster et les données traitées ne sont pas beaucoup. S'il y a une grande quantité de données qui doivent être traitées, vous pouvez définir vous-même le nombre de fragments et de répliques.
Tout d'abord, établir une connexion avec ES, CA.CRT est liée à l'auto-signature de JKS. Bien sûr, ici, j'utilise InSecureskipverify pour ignorer la vérification du fichier de certificat.
func initileLasticsearch () {pool: = x509.newcertpool () crt, err0: = ioutil.readfile ("conf / ca.crt") if err0! = nil {canepenes (err0) & tls.config {rootcas: pool, insecurskipverify: true},} httpclient: = & http.client {transport: tr} // background construction elasticclient var err error elasticclient, err = elastic.newclient (elastic.seturl (myconfig.elasturl), elastic.sether Elastic.setGzip (true), Elastic.sethttpclient (httpclient), élastique.setsniff (false), // Sniff de cluster, n'oubliez pas de fermer un seul nœud. Impossible d'opensenes (err, "search_client_error") return} // elasticClient Construction est terminé // interroger s'il existe un index de papier existe, err: = elasticclient.indexexists (myConfig.ElasticIndexName) .do (context.background ()) if err! = nil {Can’t the index (err, exis_paper_index_check ") Vérification de l'intégrité, aucune donnée n'est envoyée s'il existe {si! IsIndexIntegrity (ElasticClient) {// Supprimer l'index actuel et se préparer à reconstruire DeleterResponse, err: = elasticClient.deleteIndex (MyConfig.ElasticIndexname) .do (context.background ()) si err! = nil | TeasticIndexname) .Do (context.background ()) If err! = Nil |vel ! deleterResponse.ackNowledged {nedOpennes (err, "Delete_index_error") return}} else {return}} // Base de données de requête en arrière Type Papersearch Struct {PaperId int64 `gorm:" primaire_key; colonne: f_paper_id; type: bigInt (20) "JSON:" id "` String `gorm:" colonne: f_name; taille: 80 "json:" name "` province [] province `gorm:" Many2many: t_paper_provin JSON: "Provinces" `// Provinces pour lesquelles le papier de test est applicable} func fetchdbgetallpaperandsendtoes () {// fetch papier var allpaper [] papersearch getdb (). table (" t_papers "). find (& allpaper) // province pour i: = gamme allpaper {var allpro [] province province GetDB (). Table ("t_provincices"). Jointes ("join intérieur` t_paper_province` sur `t_paper_province`.`f_province_f_province_id` =` t_provincines`.`f_province_id`) .where ("t_paper_province.paper_f_paper_id =?", Allpaper [i] .paperId) .find (& allPro) allpaper [i] .provincces = allpro} if Len (allpaper)> 0 {// envoyer à es - créer index createService: = getElasticsearch (). CreateIndex (myconfig.elasticindexname) // the index_default_setting est le contenu dans le mapping.json. createService.body (index_default_setting) Createesult, err: = createService.do (context.background ()) if err! = nil {nedOpenes (err, "create_paper_index") Envoyer tous les papier BulkRequest: = GetEllasSicsearch (). Bulk () pour i: = plage allpaper {indexReq: = elastic.newBulkIndexRequest (). Optype ("Create"). Doc (allpaper [i]) bulkrequest.add (indexReq)} // envoie les demandes en vrac à elasticsearch bulkResponse, err: = bulkrequest.do (context.background ()) if err! = Nil {nedOpenes (err, "insert_docs_error") return} // bulk request actions get get ! = Len (allpaper) {nedOpennes (err, "insert_docs_nums_error") return} // envoyer un succès}} Après avoir exécuté le code ci-dessus, utilisez {{URL}} / _ Cat / Indices? V pour voir si l'index nouvellement créé apparaît dans ES, et utilisez {{URL}} / papiers / _search pour voir combien de documents frappent. Si le nombre de documents est égal à la quantité de données que vous avez envoyées dans le passé, le service de recherche sera envisagé en cours d'exécution.
recherche
Vous pouvez désormais rechercher des articles de test par provinceID et Q, et la valeur par défaut est triée par score de pertinence.
// Q Search String provinceid Limited Province ID Limit Page Page Pagination Paramètres Func Searchpaper (Q String, ProvinceId Uint, Limit Int, page int) (List [] PAPERSEARCH, TOTALPAGE INT, COURTYPAGE INT, PAGEIEND CourseID, GradeId, ProvinceId, PaperTypeid, Limit, Page)} List = Make ([] PAPERSIMPLE, 0) TOTALPAGE = 0 CurrentPage = Page PageiSend = 0 reverreserr = Nil Client: = GetELasticSearch () Si client == Nil {Return SearchPaperLocal (Q, CourseId, GradeId, ProvinceId, PaperTypeid, Limit, Page)} // Base de données pour rechercher si! IsIndexIntegrity (client) {return searchpaperLocal (q, CourseId, Gradeid, provinceId, PaperTypeid, limite, page)} if! Client.isrunning () {client.Start ()} Defer Client.Stop () Q = html.escapestring (q) Boolquetery: = Elastic.NewBoolQuery () Paper.Name. : = elastic.newmatchquery ("name", q) // province if provinceId> 0 && provinceId! = default_province_all {probool: = elastic.newboolQuery () tpro: = elastic.newTermQuery ("provinces.id", provinceId) PRONEST: = elastic.NewneSetedQuery ("" provincial " boolquery.must (proneste)} boolquery.must (matchquery) pour _, e: = range termquerys {boolquery.field (e)} highlightt: = elastic.newhighlight () hights.field (elastic_search_search_field_name) highlight.pretags (elastic_search_search_field_tag_tag_start) Highlight.Postags (Elastic_Search_Search_Field_Tag_end) SearchResult, err2: = client.search (myConfig.ElasticIndexName). Présentation (Highligt). Requête (boolquery). De ((page - 1) * limite). Taille (limite). Do (context.background ()) si err2! = Nil {// gère l'erreur getLogger (). Logerr ("l'erreur s'est produite lors de la recherche" + err2.error (), "search_error") // gérer l'erreur returnr = errors.new ("l'erreur s'est produite pendant la recherche")} else {si searchResult. searchResult.hits.hits {var p papersearch err: = json.unmarshal (* hit.source, & p) if err! = nil {// désérialisation a échoué getlogger (). Logerr ("Erreur s'est produite pendant la recherche" + err.error (), "Search_deseRialization_error") Retourrr = errers.NewNew ("Erreur pendant la recherche") IFFOR Len (hit.highlight [elastic_search_search_field_name])> 0 {p.name = hit.highlight [elastic_search_search_field_name] [0]} list = annex (list, p)} count: = searchResult.totalhits () currentpage = page si le compte> 0 {totalPage = int (math.ceil (float64 (Page) / compte> 0 {totalPage = int (math.ceil (float64 (Page) / Count> 0 {totalPage = int (math.ceil (float64 (Page) / Count float64 (limit)))} if currentpage> = totalpage {pageisend = 1}} else {// no hits}} return}Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.