2015-07-23 8 views
8

Mam przypadek użycia, w którym współbieżne żądania aktualizacji trafiają do mojego klastra Elasticsearch. Aby upewnić się, że nieaktualne zdarzenie (takie, które jest nieistotne dla nowszego żądania), nie aktualizuje dokumentu po tym, jak nowsze zdarzenie już dotarło do klastra, chciałbym przekazać skrypt z żądaniami aktualizacji, aby porównać pole aby ustalić, czy żądanie przychodzące jest istotne, czy nie. Żądanie będzie wyglądać następująco:Używanie skryptu do warunkowego aktualizowania dokumentu w 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 
}' 

Czy pseudo kod, który napisałem w polu "skrypt" jest dostępny w Elasticsearch? Jeśli tak, chciałbym pomóc przy składni (groovy, python lub javascript).

Wszelkie sugestie dotyczące alternatywnego podejścia będą również bardzo mile widziane.

+0

udało ci się znaleźć rozwiązanie tego? Próbowałem tego podejścia, ale nie działało. – animageofmine

+0

@animageofmine znalazłeś rozwiązanie? – Anant

+1

@ Anant spojrzeć na mój post tutaj: https://discuss.elastic.co/t/conditional-update-to-the-document/64964/16 – animageofmine

Odpowiedz

8

Elasticsearch ma wbudowane optimistic concurrency control (+ here i here).

Sposób działania polega na tym, że Update API umożliwia użycie dwóch parametrów: version w celu kontrolowania, czy aktualizacja powinna zostać wykonana, czy nie.

Wykonując powyższy przykład, pierwsza operacja indeksowania/aktualizacji utworzy dokument o numerze version: 1. Następnie weź przypadek, w którym masz dwie jednoczesne prośby. Oba komponenty A i B wyślemy zaktualizowany dokument, początkowo oba pobrały dokument za pomocą version: 1 i określą tę wersję w swoim żądaniu (zob. version=1 w ciągu zapytania poniżej). Elasticsearch zaktualizuje dokument wtedy i tylko wtedy, gdy wersja warunkiem jest taki sam jak obecny jeden

komponentu A i B zarówno wysyłać, ale zażądać jest pierwszym, aby go:

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

W tym momencie wersja dokumentu będzie miała wartość 2, a żądanie B zakończy się na HTTP 409 Conflict, ponieważ B zakłada, że ​​dokument nadal znajduje się w wersji 1, mimo że w międzyczasie wersja została zwiększona z powodu żądania A.

B może zdecydowanie pobrać dokument z nową wersją (tj. 2) i spróbować ponownie przeprowadzić aktualizację, ale tym razem pod adresem ?version=2. Jeśli jest to pierwszy, który osiągnie ES, aktualizacja się powiedzie.

+0

Dzięki za odpowiedź @ Val. Zdecydowanie uważałem, że polegam na optymistycznej kontroli współbieżności. Mechanizm tworzenia aktualizacji działa jako środkowy człowiek i wolałbym, żeby nie musiał pobierać dokumentu przed aktualizacją. Wolałbym po prostu wysłać aktualizację, a Elacticsearch zdecyduje, czy aktualizacja jest istotna, czy nie. Ten środkowy człowiek będzie znał tylko identyfikator dokumentu i dane do wprowadzenia. – bkahler

+0

@bkahler To nie jest możliwe. Najpierw musisz pobrać dokument, a następnie napisać. Wszystkie optymistyczne zamki działają na tej zasadzie. – Adi

2

myślę skrypt powinien wyglądać następująco:

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

lub

"script": "ctx._source.user_update_time > my_new_time ? ctx.op=\"none\" : ctx._source.user_update_time=my_new_time" 
Powiązane problemy