[RUBY] C'est nouveau, mais j'ai essayé d'utiliser Groonga

Que diriez-vous d'une recherche en texte intégral? J'ai donc essayé d'utiliser Groonga.  → Groonga

Recherche en texte intégral

"Recherche plein texte" est comme "recherche Google" d'une manière très simple. Entrez des mots-clés pour trouver celui que vous souhaitez parmi de nombreux documents.

Il semble y avoir divers

Donc, tout d'abord, si vous interrogez Google sur le "système de recherche en texte intégral", vous trouverez diverses choses.

etc En pensant que Namazu me manque, j'ai regardé autour de moi et j'ai trouvé que Groonga était bon, alors j'ai décidé de l'utiliser.

Installation

C'était un peu un environnement local, alors j'ai décidé de l'installer en utilisant docker-compose. # Il est également écrit dans le document officiel. .. ..

Je l'ai essayé tel qu'il est officiellement écrit

Groonga#with-docker-compose

Oh, il s'est certainement levé facilement. Pour confirmer, lancez le navigateur et entrez http: // localhost: 10041, et une page s'affichera.

J'ai essayé de le télécharger avec l'intention de coller une image, mais peu importe combien de fois je l'ai essayé, je me suis mis en colère comme suit, alors veuillez le compléter dans votre cerveau (imaginez-le). .. ..

Something went wrong

Mais. .. ..

% docker-compose run groonga Si tel est le cas, il tombera à moins que le terminal ne soit laissé en place. Ensuite, lorsque j'essaye de le redémarrer et que je dis «% docker-compose restart», cette fois, le fichier de données existe déjà. Erreur. .. ..

La raison en est que la commande -n in: [" -n "," /mnt/db/data.db "] est une option pour créer un nouveau fichier de données, donc chaque fois que j'essaie d'en créer un nouveau, je me fâche. J'ai fait.

Mumumu.

J'ai donc créé un Dockerfile et essayé de le lancer

Veuillez vous référer à la source publiée sur Github.

Je vais vous expliquer brièvement. Tout d'abord, sous / groonga.

Les paramètres de configuration, etc. sont décrits dans docker-compose.yml. J'essaye de le générer à partir de ./groonga/Dockerfile avec build:. / Groonga dedans. Utilisez volumes pour rendre le fichier de données visible même depuis la machine hôte.

Le reste de xxxx.sh semble être un outil utile. Lors de l'installation, $. / Install.sh fera quelque chose comme docker-compose build. Si vous voulez entrer dans le processus docker, entrez-le avec $. / Login.sh. Dans ce cas, utilisez $ exit pour quitter. L'arrêt est «. / Stop.sh» et le redémarrage est «. / Restart.sh». Lorsque vous n'avez plus besoin du processus docker, faites un conteneur rm docker avec $. / Remove.sh.

Ensuite, sous / groonga / groonga. Le Dockerfile a des instructions spécifiques sur la façon de le faire.

Il semble y avoir quelque chose de bogué

Si vous installez groonga normalement et y accédez via http, vous risquez de recevoir une erreur de temps en temps. Quand je l'ai recherché sur le net, j'ai trouvé l'article suivant.  → https://okamuuu.hatenablog.com/entry/2017/11/13/185903

Okamuuu Merci.

Mais cet article était en 2017 et a toujours la même erreur en 2020. .. ..

Donc stack-fix.c est un patch. J'ai écrit celui en l'incluant dans le Dockerfile. Ensuite, afin d'éviter «l'erreur lors de la création d'un nouveau fichier lors du redémarrage» plus tôt, j'ai écrit un script de démarrage, créé un fichier de données s'il n'existait pas, et l'ai utilisé s'il existait. C'est «groonga.sh».

Réinstaller

Donc, $. / Install.sh.

Allez sur http: // localhost: 10041 et oui. C'est fait.

Commençons par Ruby.

Il semble y avoir plusieurs façons d'utiliser le groonga à partir de rubis. rroonga est célèbre, mais il ressemble à une bibliothèque lorsque groonga fonctionne sur le même serveur. Il ressemble à groonga-client lorsqu'il est exécuté sur Docker ou un autre serveur (y compris virtuel).

Alors installez.

Installation ou échantillon

groonga-client est $ gem install groonga-client Vous pouvez l'installer avec.

J'ai exécuté l'exemple suivant.

test.rb


# -*- coding: utf-8 -*-
require "groonga/client"

host = "127.0.0.1"
port = 10041
Groonga::Client.open(host: host, port: port, protocol: :http) do |client|
  tables = client.table_list
  unless tables.map{|m| m.name}.include?("docs")
    # ---- create normal table ----
    client.table_create(name: "docs",
                        flags: "TABLE_HASH_KEY",
                        key_type: "ShortText")
    client.column_create(table: "docs",
                         name: "body",
                         flags: "COLUMN_SCALAR",
                         type: "Text")

    # ---- data insert to table ----
    values = [
      { "_key" => "/path/to/document/1",
        "body" => "Meros était furieux." },
      { "_key" => "/path/to/document/2",
        "body" => "Meros ne comprend pas la politique." },
      { "_key" => "/path/to/document/3",
        "body" => "Meros avait un ami de Takema." },      
    ]   
    client.load(table: "docs",
                values: values.to_json)
  end

  # ---- data search ----
  query = "perdre son sang froid"
  response = client.select(table: "docs",
                           query: query,
                           match_columns: "body")
  puts "hits: #{response.n_hits} (query: #{query} -> body)"
  response.records.each do |record|
    p record
  end

  query = "Politique"
  response = client.select(table: "docs",
                           query: "body:@#{query}")
  puts "hits: #{response.n_hits} (query: #{query} -> body)"
  response.records.each do |record|
    p record
  end

  filter = "/path/to/document/3"
  response = client.select(table: "docs",
                           filter: "_key == '#{filter}'")
  puts "hits: #{response.n_hits} (filter: #{filter} -> _key)"
  response.records.each do |record|
    p record
  end
  query = "/document"
  response = client.select(table: "docs",
                           query: "_key:@#{query}")
  puts "hits: #{response.n_hits} (query: #{query} -> _key)"
  response.records.each do |record|
    p record
  end

end

Puis exécutez.

$ ruby ./test.rb
hits: 1 (query:perdre son sang froid-> body)
{"_id"=>1, "_key"=>"/path/to/document/1", "body"=>"Meros était furieux."}
hits: 1 (query:Politique-> body)
{"_id"=>2, "_key"=>"/path/to/document/2", "body"=>"Meros ne comprend pas la politique."}
hits: 1 (filter: /path/to/document/3 -> _key)
{"_id"=>3, "_key"=>"/path/to/document/3", "body"=>"Meros avait un ami de Takema."}
hits: 3 (query: /document -> _key)
{"_id"=>1, "_key"=>"/path/to/document/1", "body"=>"Meros était furieux."}
{"_id"=>2, "_key"=>"/path/to/document/2", "body"=>"Meros ne comprend pas la politique."}
{"_id"=>3, "_key"=>"/path/to/document/3", "body"=>"Meros avait un ami de Takema."}

Ça à l'air bon.

J'ai essayé d'écrire une requête de deux manières en recherchant «rage» et «politique». En utilisant match_columns et en écrivant comme column: @ query. Pour le moment, lequel est bien?

.. .. .. Je veux dire, lorsque j'ai créé la table, je n'ai pas défini de tokenizer ou quoi que ce soit, et je n'ai pas créé de table d'index, mais je peux rechercher la colonne body comme "% rage%". .. .. Est-ce cela une question? .. ..

Je veux dire, ça ressemble à ça. Oui.

J'ai essayé de créer une table d'index

Alors, j'ai créé une table d'index. Il semble que le temps de recherche sera très rapide si vous faites cela.

test2.rb


# -*- coding: utf-8 -*-
require "groonga/client"

host = "127.0.0.1"
port = 10041
Groonga::Client.open(host: host, port: port, protocol: :http) do |client|
  tables = client.table_list
  unless tables.map{|m| m.name}.include?("doc_indexes")
    # ---- create indexes ----
    client.table_create(name: "doc_indexes",
                        flags: "TABLE_PAT_KEY",
                        key_type: "ShortText",
                        default_tokenizer: "TokenBigram",
                        normalizer: "NormalizerAuto")
    client.column_create(table: "doc_indexes",
                         name: "body_index",
                         flags: "COLUMN_INDEX|WITH_POSITION",
                         type: "docs",
                         source: "body")
  end

  query = "Je ne sais pas"
  response = client.select(table: "docs",
                           query: query,
                           match_columns: "doc_indexes.body_index")
  puts "hits: #{response.n_hits} (query: #{query} -> doc_indexes.body_index)"
  response.records.each do |record|
    p record
  end  
end

Lorsqu'il est exécuté avec

$ ruby ./test2.rb
hits: 1 (query:Je ne sais pas-> doc_indexes.body_index)
{"_id"=>2, "_key"=>"/path/to/document/2", "body"=>"Meros ne comprend pas la politique."}

J? ai compris. C'est peut-être la bonne voie à suivre. .. ..

Umm.

À propos de Groonga

Oh oui, j'ai oublié l'important. groonga est un système de base de données optimisé pour la recherche en texte intégral. C'est donc un peu différent du RDB et du KVS que j'utilise tout le temps, il est donc difficile de s'y habituer.

Avec RDB, vous pouvez créer des colonnes qui sont utilisées comme clés lors de la création d'une table, des colonnes qui stockent des données, etc., mais groonga a une structure de clé et une fonction de recherche en texte intégral lors de la création d'une table pour la première fois. Est spécifié et les colonnes sont ajoutées à la table ultérieurement. En outre, comment créer un index et comment effectuer une recherche est une impression unique. Je pense que ce sera pratique si vous pouvez le maîtriser.

c'est tout.

Recommended Posts

C'est nouveau, mais j'ai essayé d'utiliser Groonga
J'ai essayé d'utiliser Gson
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
J'ai essayé d'utiliser azure cloud-init
J'ai essayé d'utiliser Apache Wicket
J'ai essayé d'utiliser Java REPL
J'ai essayé de créer un nouvel algorithme de tri, mais je ne sais pas si c'est vraiment nouveau
J'ai essayé d'utiliser anakia + Jing maintenant
J'ai essayé d'utiliser Spring + Mybatis + DbUnit
J'ai essayé d'utiliser JOOQ avec Gradle
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé d'utiliser JWT en Java
[Android] J'ai essayé d'utiliser la disposition du coordinateur.
J'ai essayé d'utiliser le conteneur Pari gp
J'ai essayé d'utiliser WebAssembly Stadio (version 2018/4/17)
J'ai essayé d'utiliser le mémo Java LocalDate
J'ai essayé d'utiliser Google HttpClient de Java
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé d'utiliser Realm avec Swift UI
J'ai essayé d'utiliser l'outil de diagnostic Java Arthas
J'ai essayé d'utiliser UICollectionViewListCell ajouté à partir de Xcode12.
J'ai essayé d'utiliser Scalar DL avec Docker
J'ai essayé le nouveau yuan à Java
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
J'ai essayé d'utiliser Junit avec Mac VScode Maven
[Pour les débutants] J'ai essayé d'utiliser DBUnit avec Eclipse
[Pour les débutants] J'ai essayé d'utiliser JUnit 5 avec Eclipse
[Android] J'ai quitté SQLite et essayé d'utiliser Realm
J'ai fait un blackjack avec Ruby (j'ai essayé d'utiliser minitest)
[API] J'ai essayé d'utiliser l'API de recherche par code postal
J'ai essayé de mettre Tomcat
J'ai essayé youtubeDataApi.
J'ai essayé de refactoriser ①
J'ai essayé FizzBuzz.
J'ai essayé d'implémenter un serveur en utilisant Netty
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
J'ai essayé JHipster 5.1
J'ai essayé d'utiliser une connexion à une base de données dans le développement Android
J'ai essayé d'utiliser le service KMS (Key Management Service) d'Alibaba Cloud
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
J'ai essayé le nouveau profileur de fonctionnalités d'IntelliJ IDEA 2019.2.
J'ai essayé d'utiliser la boîte à outils de migration pour les fichiers binaires d'application
J'ai essayé d'utiliser l'instruction Extended for en Java
J'ai essayé de gratter un graphique boursier en utilisant Java (Jsoup)
[J'ai essayé] Tutoriel de printemps
J'ai essayé d'exécuter Autoware
J'ai essayé Spring Batch
J'ai essayé node-jt400 (Programmes)
J'ai essayé node-jt400 (exécuter)
J'ai essayé node-jt400 (Transactions)
J'ai essayé un test unitaire de l'application Rails en utilisant RSpec et FactoryBot
J'ai essayé d'utiliser le référentiel GitHub comme serveur de bibliothèque
[Rails] J'ai essayé d'utiliser la méthode button_to pour la première fois
J'ai essayé de construire l'environnement petit à petit en utilisant docker