2015-07-23 9 views
8

Ho un caso d'uso in cui le richieste di aggiornamento simultanee colpiscono il mio cluster Elasticsearch. Per assicurarsi che un evento obsoleto (reso irrilevante da una nuova richiesta) non aggiorni un documento dopo che un nuovo evento ha già raggiunto il cluster, vorrei passare uno script con le mie richieste di aggiornamento per confrontare un campo per determinare se la richiesta in arrivo è rilevante o meno. La richiesta sarebbe simile a questa:Utilizzo di uno script per aggiornare in modo condizionale un documento in Elasticsearch

curl -XPOST 'localhost:9200/test/type1/1/_update' -d ' 
{ 
    "script": " IF ctx._source.user_update_time > my_new_time THEN do not update ELSE proceed with update", 
    "params": { 
    "my_new_time": "2014-09-01T17:36:17.517"" 
    }, 
    "doc": { 
    "name": "new_name" 
    }, 
    "doc_as_upsert": true 
}' 

è il codice pseudo che ho scritto nel campo "script" possibile in elasticsearch? Se è così, mi piacerebbe un aiuto con la sintassi (groovy, python o javascript).

Qualsiasi suggerimento di approccio alternativo sarebbe molto apprezzato anche.

+0

sono stati in grado di trovare una soluzione a questo? Ho provato questo approccio ma non ha funzionato. – animageofmine

+0

@animageofmine hai trovato una soluzione? – Anant

+1

@Anant guarda il mio post qui: https://discuss.elastic.co/t/conditional-update-to-the-document/64964/16 – animageofmine

risposta

8

Elasticsearch ha incorporato optimistic concurrency control (+ here e here).

Il modo in cui funziona è che lo Update API consente a due di utilizzare il parametro version per controllare se l'aggiornamento deve procedere o meno.

Quindi, seguendo l'esempio sopra riportato, la prima operazione di indice/aggiornamento creerebbe un documento con version: 1. Quindi prendi il caso in cui hai due richieste simultanee. Entrambi i componenti A e B invieranno un documento aggiornato, inizialmente hanno entrambi recuperato il documento con version: 1 e specificheranno tale versione nella loro richiesta (vedere version=1 nella stringa di query riportata di seguito). Elasticsearch aggiornerà il documento se e solo se la versione fornita è la stessa di quella attuale

Componente A e B, sia inviare questa, ma la richiesta di A è il primo a farlo:

curl -XPOST 'localhost:9200/test/type1/1/_update?version=1' -d '{ 
    "doc": { 
    "name": "new_name" 
    }, 
    "doc_as_upsert": true 
}' 

A questo punto la versione del documento sarà 2 e la richiesta di B finirà con HTTP 409 Conflict, perché B presuppone che il documento sia ancora alla versione 1, anche se la versione è aumentata nel frattempo a causa della richiesta di A.

B può sicuramente recuperare il documento con la nuova versione (ad esempio 2) e riprovare l'aggiornamento, ma questa volta con ?version=2 nell'URL. Se è il primo a raggiungere ES, l'aggiornamento avrà successo.

+0

Grazie per la risposta @Val. Ho sicuramente considerato di fare affidamento sul controllo ottimistico della concorrenza per questo. Il meccanismo che rende gli aggiornamenti agisce come un intermediario e preferirei che non fosse necessario recuperare un documento prima di aggiornarlo. Preferirei semplicemente inviare un aggiornamento e far decidere a Elacticsearch se l'aggiornamento è pertinente o meno. Questo intermediario conoscerà solo l'ID del documento e i dati da inserire. – bkahler

+0

@bkahler Questo non è possibile. Dovrai prima recuperare il documento e poi scrivere. Tutte le serrature ottimistiche funzionano su questo principio. – Adi

2

penso che lo script dovrebbe essere simile a questo:

"script": "if(ctx._source.user_update_time > my_new_time) ctx._source.user_update_time=my_new_time;" 

o

"script": "ctx._source.user_update_time > my_new_time ? ctx.op=\"none\" : ctx._source.user_update_time=my_new_time" 
Problemi correlati