Comment utiliser Elasticsearch avec MongoDB?

152

J'ai parcouru de nombreux blogs et sites sur la configuration d'Elasticsearch pour MongoDB pour indexer les collections dans MongoDB, mais aucun d'entre eux n'était simple.

Veuillez m'expliquer un processus étape par étape pour installer elasticsearch, qui devrait inclure:

  • configuration
  • exécuter dans le navigateur

J'utilise Node.js avec express.js, alors aidez-moi en conséquence.

bibin david
la source
4
Remarque: les rivières sont obsolètes
abdul qayyum

Réponses:

287

Cette réponse devrait être suffisante pour vous permettre de suivre ce didacticiel sur la création d'un composant de recherche fonctionnel avec MongoDB, Elasticsearch et AngularJS .

Si vous cherchez à utiliser la recherche à facettes avec les données d'une API, le BirdWatch Repo de Matthiasn est quelque chose que vous voudrez peut-être regarder.

Voici donc comment vous pouvez configurer un "cluster" Elasticsearch à nœud unique pour indexer MongoDB à utiliser dans une application NodeJS, Express sur une nouvelle instance EC2 Ubuntu 14.04.

Assurez-vous que tout est à jour.

sudo apt-get update

Installez NodeJS.

sudo apt-get install nodejs
sudo apt-get install npm

Installez MongoDB - Ces étapes proviennent directement de la documentation MongoDB. Choisissez la version avec laquelle vous êtes à l'aise. Je m'en tiens à la v2.4.9 car elle semble être la version la plus récente que MongoDB-River prend en charge sans problème.

Importez la clé GPG publique MongoDB.

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10

Mettez à jour votre liste de sources.

echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list

Obtenez le package 10gen.

sudo apt-get install mongodb-10gen

Ensuite, choisissez votre version si vous ne voulez pas la plus récente. Si vous configurez votre environnement sur une machine Windows 7 ou 8, restez à l'écart de la version 2.6 jusqu'à ce qu'ils résolvent certains bogues en l'exécutant en tant que service.

apt-get install mongodb-10gen=2.4.9

Empêchez la version de votre installation MongoDB d'être modifiée lors de la mise à jour.

echo "mongodb-10gen hold" | sudo dpkg --set-selections

Démarrez le service MongoDB.

sudo service mongodb start

Par défaut, vos fichiers de base de données sont / var / lib / mongo et vos fichiers journaux / var / log / mongo.

Créez une base de données via le shell mongo et insérez-y des données factices.

mongo YOUR_DATABASE_NAME
db.createCollection(YOUR_COLLECTION_NAME)
for (var i = 1; i <= 25; i++) db.YOUR_COLLECTION_NAME.insert( { x : i } )

Maintenant, pour convertir le MongoDB autonome en un jeu de répliques .

Arrêtez d'abord le processus.

mongo YOUR_DATABASE_NAME
use admin
db.shutdownServer()

Maintenant, nous exécutons MongoDB en tant que service, donc nous ne passons pas l'option "--replSet rs0" dans l'argument de ligne de commande lorsque nous redémarrons le processus mongod. Au lieu de cela, nous le mettons dans le fichier mongod.conf.

vi /etc/mongod.conf

Ajoutez ces lignes, en remplaçant vos chemins de base de données et de journal.

replSet=rs0
dbpath=YOUR_PATH_TO_DATA/DB
logpath=YOUR_PATH_TO_LOG/MONGO.LOG

Ouvrez à nouveau le shell mongo pour initialiser le jeu de répliques.

mongo DATABASE_NAME
config = { "_id" : "rs0", "members" : [ { "_id" : 0, "host" : "127.0.0.1:27017" } ] }
rs.initiate(config)
rs.slaveOk() // allows read operations to run on secondary members.

Installez maintenant Elasticsearch. Je suis juste ce Gist utile .

Assurez-vous que Java est installé.

sudo apt-get install openjdk-7-jre-headless -y

Restez avec la v1.1.x pour le moment jusqu'à ce que le bogue du plugin Mongo-River soit corrigé dans la v1.2.1.

wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.1.1.deb
sudo dpkg -i elasticsearch-1.1.1.deb

curl -L http://github.com/elasticsearch/elasticsearch-servicewrapper/tarball/master | tar -xz
sudo mv *servicewrapper*/service /usr/local/share/elasticsearch/bin/
sudo rm -Rf *servicewrapper*
sudo /usr/local/share/elasticsearch/bin/service/elasticsearch install
sudo ln -s `readlink -f /usr/local/share/elasticsearch/bin/service/elasticsearch` /usr/local/bin/rcelasticsearch

Assurez-vous que /etc/elasticsearch/elasticsearch.yml a les options de configuration suivantes activées si vous ne développez que sur un seul nœud pour le moment:

cluster.name: "MY_CLUSTER_NAME"
node.local: true

Démarrez le service Elasticsearch.

sudo service elasticsearch start

Vérifiez que cela fonctionne.

curl http://localhost:9200

Si vous voyez quelque chose comme ça, vous êtes bon.

{
  "status" : 200,
  "name" : "Chi Demon",
  "version" : {
    "number" : "1.1.2",
    "build_hash" : "e511f7b28b77c4d99175905fac65bffbf4c80cf7",
    "build_timestamp" : "2014-05-22T12:27:39Z",
    "build_snapshot" : false,
    "lucene_version" : "4.7"
  },
  "tagline" : "You Know, for Search"
}

Installez maintenant les plugins Elasticsearch pour qu'il puisse jouer avec MongoDB.

bin/plugin --install com.github.richardwilly98.elasticsearch/elasticsearch-river-mongodb/1.6.0
bin/plugin --install elasticsearch/elasticsearch-mapper-attachments/1.6.0

Ces deux plugins ne sont pas nécessaires, mais ils sont utiles pour tester les requêtes et visualiser les modifications apportées à vos index.

bin/plugin --install mobz/elasticsearch-head
bin/plugin --install lukas-vlcek/bigdesk

Redémarrez Elasticsearch.

sudo service elasticsearch restart

Indexez enfin une collection de MongoDB.

curl -XPUT localhost:9200/_river/DATABASE_NAME/_meta -d '{
  "type": "mongodb",
  "mongodb": {
    "servers": [
      { "host": "127.0.0.1", "port": 27017 }
    ],
    "db": "DATABASE_NAME",
    "collection": "ACTUAL_COLLECTION_NAME",
    "options": { "secondary_read_preference": true },
    "gridfs": false
  },
  "index": {
    "name": "ARBITRARY INDEX NAME",
    "type": "ARBITRARY TYPE NAME"
  }
}'

Vérifiez que votre index est dans Elasticsearch

curl -XGET http://localhost:9200/_aliases

Vérifiez la santé de votre cluster.

curl -XGET 'http://localhost:9200/_cluster/health?pretty=true'

Il est probablement jaune avec des fragments non attribués. Nous devons dire à Elasticsearch avec quoi nous voulons travailler.

curl -XPUT 'localhost:9200/_settings' -d '{ "index" : { "number_of_replicas" : 0 } }'

Vérifiez à nouveau la santé du cluster. Il devrait être vert maintenant.

curl -XGET 'http://localhost:9200/_cluster/health?pretty=true'

Va jouer.

Donald Gary
la source
@ Duck5auce n'a aucune idée de la façon d'obtenir le résultat (le résultat de la recherche élastique) par express.js et de l'afficher dans le navigateur en utilisant un modèle jade ou ejs, par exemple comme app.get ('search = "google"', function (req , res) {}); et merci pour la merveilleuse réponse
bibin david
@bibindavid Je vérifierais cette ressource. Il vous guide tout au long de la création d'un module client ES côté serveur dans lequel vous transmettez des requêtes filtrées via deux autres modules personnalisés. Le rendu des données est toujours géré sur le client, mais cela devrait être un bon point de départ. sahan.me/posts/dabbling-in-elasticsearch-part-2-with-nodejs Github repo situé ici: github.com/sahan/sahan.github.io/tree/master/resources/…
Donald Gary
Pouvez-vous me dire quel sera le meilleur mongoosastic ou utiliser différemment le module de mangose ​​et elasticsearch ????
Sudhanshu Gaur
7
Cela fait un an depuis l'excellente réponse de duck5auce. Je pense que les gens utilisent maintenant 10gens [mongo-connector] [1] pour synchroniser un cluster MongoDB avec ElasticSearch en temps réel. Il suit l'oplog MongoDB. [1]: github.com/10gen-labs/mongo-connector/wiki/…
Andrew Betts
8
@ duck5auce Veuillez mettre à jour cette réponse, elle est obsolète. River est obsolète
tsturzl
36

L'utilisation de la rivière peut présenter des problèmes lorsque votre opération évolue. River utilisera une tonne de mémoire lorsqu'il est soumis à de lourdes opérations. Je vous recommande de mettre en œuvre vos propres modèles elasticsearch, ou si vous utilisez mangouste, vous pouvez y intégrer vos modèles elasticsearch ou utiliser mongoosastic qui le fait essentiellement pour vous.

Un autre inconvénient de Mongodb River est que vous serez bloqué en utilisant la branche mongodb 2.4.x et ElasticSearch 0.90.x. Vous commencerez à découvrir que vous manquez de nombreuses fonctionnalités vraiment intéressantes, et le projet mongodb river ne produit tout simplement pas un produit utilisable assez rapidement pour rester stable. Cela dit, Mongodb River n'est certainement pas quelque chose avec lequel je voudrais entrer en production. Cela a posé plus de problèmes que sa valeur. Il abandonnera aléatoirement l'écriture sous une charge importante, il consommera beaucoup de mémoire et il n'y a pas de paramètre pour limiter cela. De plus, River ne se met pas à jour en temps réel, il lit les oplogs de mongodb, ce qui peut retarder les mises à jour jusqu'à 5 minutes selon mon expérience.

Nous avons récemment dû réécrire une grande partie de notre projet, car c'est une occurrence hebdomadaire que quelque chose ne va pas avec ElasticSearch. Nous étions même allés jusqu'à embaucher un consultant Dev Ops, qui reconnaît également qu'il est préférable de s'éloigner de River.

METTRE À JOUR: Elasticsearch-mongodb-river prend désormais en charge ES v1.4.0 et mongodb v2.6.x. Cependant, vous rencontrerez toujours des problèmes de performances lors d'opérations d'insertion / mise à jour lourdes car ce plugin tentera de lire les oplogs de mongodb pour les synchroniser. S'il y a beaucoup d'opérations depuis le déverrouillage du verrou (ou plutôt du verrou), vous remarquerez une utilisation extrêmement élevée de la mémoire sur votre serveur elasticsearch. Si vous prévoyez d'avoir une grande opération, la rivière n'est pas une bonne option. Les développeurs d'ElasticSearch vous recommandent toujours de gérer vos propres index en communiquant directement avec leur API en utilisant la bibliothèque cliente de votre langage, plutôt qu'en utilisant River. Ce n'est pas vraiment le but de la rivière. Twitter-river est un excellent exemple d'utilisation de la rivière. C'est essentiellement un excellent moyen de trouver des données à partir de sources extérieures,

Considérez également que mongodb-river est en retard dans la version, car il n'est pas maintenu par ElasticSearch Organization, il est maintenu par un tiers. Le développement était bloqué sur la branche v0.90 pendant longtemps après la sortie de la v1.0, et lorsqu'une version pour v1.0 a été publiée, il n'était pas stable jusqu'à ce qu'elasticsearch publie la v1.3.0. Les versions de Mongodb sont également en retard. Vous pouvez vous retrouver dans une situation difficile lorsque vous cherchez à passer à une version ultérieure de chacun, en particulier avec ElasticSearch sous un développement aussi lourd, avec de nombreuses fonctionnalités très attendues en cours. Rester à jour sur la dernière ElasticSearch a été très important car nous comptons fortement sur l'amélioration constante de notre fonctionnalité de recherche en tant qu'élément central de notre produit.

Dans l'ensemble, vous obtiendrez probablement un meilleur produit si vous le faites vous-même. Ce n'est pas si difficile. C'est juste une autre base de données à gérer dans votre code, et elle peut facilement être ajoutée à vos modèles existants sans refactorisation majeure.

tsturzl
la source
Avez-vous un lien ou un conseil où je peux indexer les informations de l'auteur dans l'index de publication puisque la publication et l'auteur sont dans 2 collections et un lien via referenceone et referencemany
Marcel Djaman
Lisez ceci pour un peu de contexte élastique.co
guide/en
Le cela vous expliquer comment vous joindre / relier les données relatives elastic.co/guide/en/elasticsearch/guide/current/...
tsturzl
1
Elasticsearch est une base de données de stockage de documents, plutôt qu'une base de données relationnelle. Il n'est pas impossible de relier des données dans elasticsearch, mais la dénormalisation est plus susceptible de se produire, mais peut être gérée avec une logique supplémentaire (il existe des plugins). La manière la plus courante de relier des données, comme indiqué dans le lien ci-dessus, consiste à stocker une référence d'identification dans le document relatif. Assurez-vous de stocker cet identifiant dans un champ défini sur not_analyzed, sinon vous aurez du mal à le rechercher, faites en sorte que les champs analysés soient tokenisés.
tsturzl
4

J'ai trouvé mongo-connector utile. Il s'agit de Mongo Labs (MongoDB Inc.) et peut être utilisé maintenant avec Elasticsearch 2.x

Gestionnaire de documentation Elastic 2.x: https://github.com/mongodb-labs/elastic2-doc-manager

mongo-connector crée un pipeline à partir d'un cluster MongoDB vers un ou plusieurs systèmes cibles, tels que Solr, Elasticsearch ou un autre cluster MongoDB. Il synchronise les données de MongoDB avec la cible, puis suit le journal d'opération MongoDB, en suivant les opérations de MongoDB en temps réel. Il a été testé avec Python 2.6, 2.7 et 3.3+. Une documentation détaillée est disponible sur le wiki.

https://github.com/mongodb-labs/mongo-connector https://github.com/mongodb-labs/mongo-connector/wiki/Usage%20with%20ElasticSearch

Lokendra Chauhan
la source
4

River est une bonne solution une fois que vous souhaitez avoir une synchronisation presque en temps réel et une solution générale.

Si vous avez déjà des données dans MongoDB et que vous souhaitez les envoyer très facilement à Elasticsearch comme "one-shot", vous pouvez essayer mon package dans Node.js https://github.com/itemsapi/elasticbulk .

Il utilise les flux Node.js afin que vous puissiez importer des données de tout ce qui prend en charge les flux (c'est-à-dire MongoDB, PostgreSQL, MySQL, fichiers JSON, etc.)

Exemple pour MongoDB vers Elasticsearch:

Installer les packages:

npm install elasticbulk
npm install mongoose
npm install bluebird

Créez un script ie script.js:

const elasticbulk = require('elasticbulk');
const mongoose = require('mongoose');
const Promise = require('bluebird');
mongoose.connect('mongodb://localhost/your_database_name', {
  useMongoClient: true
});

mongoose.Promise = Promise;

var Page = mongoose.model('Page', new mongoose.Schema({
  title: String,
  categories: Array
}), 'your_collection_name');

// stream query 
var stream = Page.find({
}, {title: 1, _id: 0, categories: 1}).limit(1500000).skip(0).batchSize(500).stream();

elasticbulk.import(stream, {
  index: 'my_index_name',
  type: 'my_type_name',
  host: 'localhost:9200',
})
.then(function(res) {
  console.log('Importing finished');
})

Envoyez vos données:

node script.js

Ce n'est pas extrêmement rapide mais cela fonctionne pour des millions d'enregistrements (grâce aux flux).


la source
3

Voici comment faire cela sur mongodb 3.0. J'ai utilisé ce joli blog

  1. Installez mongodb.
  2. Créez des répertoires de données:
$ mkdir RANDOM_PATH/node1
$ mkdir RANDOM_PATH/node2> 
$ mkdir RANDOM_PATH/node3
  1. Démarrer les instances Mongod
$ mongod --replSet test --port 27021 --dbpath node1
$ mongod --replSet test --port 27022 --dbpath node2
$ mongod --replSet test --port 27023 --dbpath node3
  1. Configurez le jeu de réplicas:
$ mongo
config = {_id: 'test', members: [ {_id: 0, host: 'localhost:27021'}, {_id: 1, host: 'localhost:27022'}]};    
rs.initiate(config);
  1. Installation d'Elasticsearch:
a. Download and unzip the [latest Elasticsearch][2] distribution

b. Run bin/elasticsearch to start the es server.

c. Run curl -XGET http://localhost:9200/ to confirm it is working.
  1. Installation et configuration de la rivière MongoDB:

$ bin / plugin --install com.github.richardwilly98.elasticsearch / elasticsearch-river-mongodb

$ bin / plugin --installe elasticsearch / elasticsearch-mapper-attachments

  1. Créez la «rivière» et l'index:

curl -XPUT ' http: // localhost: 8080 / _river / mongodb / _meta ' -d '{"type": "mongodb", "mongodb": {"db": "mydb", "collection": "foo" }, "index": {"name": "name", "type": "random"}} '

  1. Test sur navigateur:

    http: // localhost: 9200 / _search? q = home

Priyanshu Chauhan
la source
6
ElasticSearch a désapprouvé les plugins de rivière. Ce n'est certainement pas la meilleure façon de maintenir un index de recherche.
tsturzl
3

Ici, j'ai trouvé une autre bonne option pour migrer vos données MongoDB vers Elasticsearch. Un démon go qui synchronise mongodb avec elasticsearch en temps réel. C'est le Monstache. Il est disponible à: Monstache

Ci-dessous le setp initial pour le configurer et l'utiliser.

Étape 1:

C:\Program Files\MongoDB\Server\4.0\bin>mongod --smallfiles --oplogSize 50 --replSet test

Étape 2 :

C:\Program Files\MongoDB\Server\4.0\bin>mongo

C:\Program Files\MongoDB\Server\4.0\bin>mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.2
Server has startup warnings:
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten]
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten]
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server.
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2019-01-18T16:56:44.931+0530 I CONTROL  [initandlisten]
MongoDB Enterprise test:PRIMARY>

Étape 3: Vérifiez la réplication.

MongoDB Enterprise test:PRIMARY> rs.status();
{
        "set" : "test",
        "date" : ISODate("2019-01-18T11:39:00.380Z"),
        "myState" : 1,
        "term" : NumberLong(2),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1547811537, 1),
                        "t" : NumberLong(2)
                },
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1547811537, 1),
                        "t" : NumberLong(2)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1547811537, 1),
                        "t" : NumberLong(2)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1547811537, 1),
                        "t" : NumberLong(2)
                }
        },
        "lastStableCheckpointTimestamp" : Timestamp(1547811517, 1),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "localhost:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 736,
                        "optime" : {
                                "ts" : Timestamp(1547811537, 1),
                                "t" : NumberLong(2)
                        },
                        "optimeDate" : ISODate("2019-01-18T11:38:57Z"),
                        "syncingTo" : "",
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1547810805, 1),
                        "electionDate" : ISODate("2019-01-18T11:26:45Z"),
                        "configVersion" : 1,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1547811537, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1547811537, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}
MongoDB Enterprise test:PRIMARY>

Étape 4. Téléchargez le " https://github.com/rwynn/monstache/releases ". Décompressez le téléchargement et ajustez votre variable PATH pour inclure le chemin d'accès au dossier de votre plate-forme. Aller à cmd et tapez"monstache -v" # 4.13.1 Monstache utilise le format TOML pour sa configuration. Configurez le fichier pour la migration nommé config.toml

Étape 5.

Mon config.toml ->

mongo-url = "mongodb://127.0.0.1:27017/?replicaSet=test"
elasticsearch-urls = ["http://localhost:9200"]

direct-read-namespaces = [ "admin.users" ]

gzip = true
stats = true
index-stats = true

elasticsearch-max-conns = 4
elasticsearch-max-seconds = 5
elasticsearch-max-bytes = 8000000 

dropped-collections = false
dropped-databases = false

resume = true
resume-write-unsafe = true
resume-name = "default"
index-files = false
file-highlighting = false
verbose = true
exit-after-direct-reads = false

index-as-update=true
index-oplog-time=true

Étape 6.

D:\15-1-19>monstache -f config.toml

Monstache en cours ...

Confirmer les données migrées chez Elasticsearch

Ajouter un enregistrement à Mongo

Monstache a capturé l'événement et migré les données vers elasticsearch

Abhijit Bashetti
la source
3

Étant donné que mongo-connector semble maintenant mort, mon entreprise a décidé de créer un outil pour utiliser les flux de modifications Mongo pour les envoyer vers Elasticsearch.

Nos premiers résultats semblent prometteurs. Vous pouvez le vérifier sur https://github.com/electionsexperts/mongo-stream . Nous sommes encore au début du développement et nous serions heureux de recevoir des suggestions ou des contributions.

Jud
la source