web-dev-qa-db-fra.com

Puis-je créer un document avec l'API de mise à jour si le document n'existe pas encore

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!

22
razafinr

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
}
43
rclement

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"
}'
5
Ashalynd

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});
1
Amio.io

À 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
0
spyle