J'ai un fichier JSON et je dois l'indexer sur le serveur ElasticSearch.
Le fichier JSOIN ressemble à ceci:
{
"sku": "1",
"vbid": "1",
"created": "Sun, 05 Oct 2014 03:35:58 +0000",
"updated": "Sun, 06 Mar 2016 12:44:48 +0000",
"type": "Single",
"downloadable-duration": "perpetual",
"online-duration": "365 days",
"book-format": "ePub",
"build-status": "In Inventory",
"description": "On 7 August 1914, a week before the Battle of Tannenburg and two weeks before the Battle of the Marne, the French army attacked the Germans at Mulhouse in Alsace. Their objective was to recapture territory which had been lost after the Franco-Prussian War of 1870-71, which made it a matter of pride for the French. However, after initial success in capturing Mulhouse, the Germans were able to reinforce more quickly, and drove them back within three days. After forty-three years of peace, this was the first test of strength between France and Germany. In 1929 Karl Deuringer wrote the official history of the battle for the Bavarian Army, an immensely detailed work of 890 pages; First World War expert and former army officer Terence Zuber has translated this study and edited it down to more accessible length, to produce the first account in English of the first major battle of the First World War.",
"publication-date": "07/2014",
"author": "Deuringer, Karl",
"title": "The First Battle of the First World War: Alsace-Lorraine",
"sort-title": "First Battle of the First World War: Alsace-Lorraine",
"edition": "0",
"sampleable": "false",
"page-count": "0",
"print-drm-text": "This title will only allow printing of 2 consecutive pages at a time.",
"copy-drm-text": "This title will only allow copying of 2 consecutive pages at a time.",
"kind": "book",
"fro": "false",
"distributable": "true",
"subjects": {
"subject": [
{
"-schema": "bisac",
"-code": "HIS027090",
"#text": "World War I"
},
{
"-schema": "coursesmart",
"-code": "cs.soc_sci.hist.milit_hist",
"#text": "Social Sciences -> History -> Military History"
}
]
},
"pricelist": {
"publisher-list-price": "0.0",
"digital-list-price": "7.28"
},
"publisher": {
"publisher-name": "The History Press",
"imprint-name": "The History Press Ireland"
},
"aliases": {
"eisbn-canonical": "1",
"isbn-canonical": "1",
"print-isbn-canonical": "9780752460864",
"isbn13": "1",
"isbn10": "0750951796",
"additional-isbns": {
"isbn": [
{
"-type": "print-isbn-10",
"#text": "0752460862"
},
{
"-type": "print-isbn-13",
"#text": "97807524608"
}
]
}
},
"owner": {
"company": {
"id": "1893",
"name": "The History Press"
}
},
"distributor": {
"company": {
"id": "3658",
"name": "asc"
}
}
}
Mais quand j'essaye d'indexer ce fichier JSON en utilisant la commande
curl -XPOST 'http://localhost:9200/_bulk' -d @1.json
Je reçois cette erreur:
{"error":{"root_cause":[{"type":"action_request_validation_exception","reason":"Validation Failed: 1: no requests added;"}],"type":"action_request_validation_exception","reason":"Validation Failed: 1: no requests added;"},"status":400}
Je ne sais pas où je fais une erreur.
L'API en bloc d'Elasticsearch utilise une syntaxe spéciale, constituée en fait de documents json
écrits sur une seule ligne. Jetez un coup d'œil à la documentation .
La syntaxe est assez simple. Pour l'indexation, la création et la mise à jour, vous avez besoin de 2 documents JSON d'une seule ligne. La première ligne indique l'action, la seconde le document à indexer/créer/mettre à jour. Pour supprimer un document, il suffit de la ligne d'action. Par exemple (à partir de la documentation):
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value1" }
{ "create" : { "_index" : "test", "_type" : "type1", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1"} }
{ "doc" : {"field2" : "value2"} }
{ "delete" : { "_index" : "test", "_type" : "type1", "_id" : "2" } }
N'oubliez pas de terminer votre fichier avec une nouvelle ligne. Ensuite, pour appeler l’API en bloc, utilisez la commande suivante:
curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"
De la documentation:
Si vous fournissez un fichier texte à curl, vous devez utiliser l’indicateur
--data-binary
au lieu de plain-d
.
J'avais un problème similaire dans le sens où je voulais supprimer un document spécifique d'un type spécifique et, grâce à la réponse ci-dessus, j'ai finalement réussi à faire fonctionner mon script bash simple!
J'ai un fichier qui a un document_id par ligne (document_id.txt) et en utilisant le script bash ci-dessous, je peux supprimer des documents d'un certain type avec le document_id mentionné.
Voici à quoi ressemble le fichier:
c476ce18803d7ed3708f6340fdfa34525b20ee90
5131a30a6316f221fe420d2d3c0017a76643bccd
08ebca52025ad1c81581a018febbe57b1e3ca3cd
496ff829c736aa311e2e749cec0df49b5a37f796
87c4101cb10d3404028f83af1ce470a58744b75c
37f0daf7be27cf081e491dd445558719e4dedba1
Le script bash ressemble à ceci:
#!/bin/bash
es_cluster="http://localhost:9200"
index="some-index"
doc_type="some-document-type"
for doc_id in `cat document_id.txt`
do
request_string="{\"delete\" : { \"_type\" : \"${doc_type}\", \"_id\" : \"${doc_id}\" } }"
echo -e "${request_string}\r\n\r\n" | curl -s -XPOST "${es_cluster}/${index}/${doc_type}/_bulk" --data-binary @-
echo
done
Le truc, après beaucoup de frustration, consistait à utiliser l’option -e pour faire écho et ajouter\n\n à la sortie de l’écho avant que je l’incline dans curl.
Et puis dans curl, j’ai alors l’option --data-binary définie pour l’empêcher de supprimer le\n\n nécessaire pour le _bulk endpoint suivi du @ - option pour le faire lire à partir de stdin!