J'ai une question très simple:
Je souhaite mettre à jour plusieurs documents dans elasticsearch. Parfois, le document existe déjà mais parfois pas. Je ne souhaite pas utiliser une requête get pour vérifier l'existence du document (cela diminue mes performances). Je souhaite utiliser directement ma demande de mise à jour pour indexer directement le document s'il n'existe pas encore.
Je sais que nous pouvons utiliser upsert pour créer un champ non existant lors de la mise à jour d'un document, mais ce n'est pas ce que je veux. Je veux indexer le document s'il n'existe pas. Je ne sais pas si upsert peut le faire.
Pouvez-vous me fournir des explications?
Merci d'avance!
Ceci est faisable en utilisant l'API de mise à jour. Vous devez définir l'identifiant de chaque document, car l'interface de mise à jour nécessite l'identifiant du document pour déterminer sa présence.
Étant donné un index créé avec les documents suivants:
PUT /cars/car/1
{ "color": "blue", "brand": "mercedes" }
PUT /cars/car/2
{ "color": "blue", "brand": "toyota" }
Nous pouvons obtenir la fonctionnalité Upsert de votre choix en utilisant l’API de mise à jour avec l’appel suivant.
POST /cars/car/3/_update
{
"doc": {
"color" : "brown",
"brand" : "ford"
},
"doc_as_upsert" : true
}
Cet appel à l'API ajoutera le document à l'index puisqu'il n'existe pas.
Si vous lancez l'appel une deuxième fois après avoir changé la couleur de la voiture, le document sera mis à jour au lieu de créer un nouveau document.
POST /cars/car/3/_update
{
"doc": {
"color" : "black",
"brand" : "ford"
},
"doc_as_upsert" : true
}
Autant que je sache, lorsque vous indexez les documents (avec un appel PUT), la version existante est remplacée par la version la plus récente. Si le document n'existait pas, il est créé. Il n'est pas nécessaire de faire la distinction entre INSERT et UPDATE dans ElasticSearch.
UPDATE: Selon la documentation , si vous utilisez op_type = create ou une version spéciale de _create de l'appel d'indexation, tout appel d'un document déjà existant échouera.
Citation de la documentation:
Here is an example of using the op_type parameter:
$ curl -XPUT 'http://localhost:9200/Twitter/Tweet/1?op_type=create' -d '{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'
Another option to specify create is to use the following uri:
$ curl -XPUT 'http://localhost:9200/Twitter/Tweet/1/_create' -d '{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'
Pour l'utilisation en bloc d'API
bulks.Push({
update: {
_index: 'index',
_type: 'type',
_id: id
}
});
bulks.Push({"doc_as_upsert":true, "doc": your_doc});
À partir de elasticsearch-model v0.1.4, les upserts ne sont pas pris en charge. J'ai pu contourner ce problème en créant un rappel personnalisé .
after_commit on: :update do
begin
__elasticsearch__.update_document
rescue Elasticsearch::Transport::Transport::Errors::NotFound
__elasticsearch__.index_document
end
end