2017-01-26 7 views
0

IDのないドキュメントを作成または更新しようとしています。 私は現在、既存の(またはそうでない)ドキュメントを検索/フェッチし、更新して戻しています。質問によるアップサイド

しかし、私は一度にすべてをやりたいと思います。

私はupdate by queryについて読んだことがありますが、このケースではうまくいきません。 また、私はスクリプトを使用しようとしましたが、更新用の参照のみが見つかりました(IDが必要です)。

これがESでも可能であるかどうかはわかりません。

ヘルプ/ヒントは高く評価されています。

おかげ


さらに詳しい情報:私は、クエリによって更新に

意図なぜ私はIDを持つ直接の関係を持っていない私の場合は

、つまり、私が持っている文書は次のように単純です:

{ 
    "text": "some text", 
    "type": "a real type", 
    "occurences": 2 
} 

だから私はそれをテキストとタイプキーの両方で一致させる必要があります。それは、それが発見された場合、それは、(発生箇所1とで)新しいドキュメントを追加する必要が存在しない場合、それは発生箇所 3.

update_by_queryのマニュアルを参照して後に更新する必要があり、それが可能でなければなりません

POST /test/type/_update_by_query?conflicts=proceed 
{ 
    "query": { 
    "bool": { 
     "must": [ 
     {"match_phrase": {"text": "some text"}}, 
     {"match_phrase": {"type": "a real type"}} 
     ] 
    } 
    } 
} 

しかし、私はここからどうやって行くのか分かりません。

+0

それが可能だ。この[doc](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html#upserts)を確認してください。 –

+0

ありがとう、私はそれを試して、結果を投稿するつもりです:) – mloureiro

+0

私は彼らのためのIDを持っていないので、それを動作させることができませんでした。私は[このメソッド](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/docs-update.html#_literal_scripted_upsert_literal)を使用しようとしました – mloureiro

答えて

0

ダイナミック生成IDを格納せずに使用した場合、正確な問題が発生しました。

私は1つのクエリで行うことはできませんと信じていますが、_update_by_queryを使用して更新カウントにレスポンスボディをチェックし、それが0であるならば、あなたは安全に新しいインスタンスを挿入することができます。

ので、あなたのケースでは、このようなものになるだろう:

POST /test/type/_update_by_query 
    { 
     "script": { 
     "inline": "ctx._source.occurences++" 
     }, 
     "query": { 
     "bool": { 
      "must": [ 
      {"match_phrase": {"text": "some text"}}, 
      {"match_phrase": {"type": "a real type"}} 
      ] 
     } 
     } 
    } 

応答は次のようになります。

{ 
      "took": 2, 
      "timed_out": false, 
      "total": 0, 
      "updated": 0, 
      "deleted": 0, 
      "batches": 0, 
      "version_conflicts": 0, 
      "noops": 0, 
      "retries": { 
       "bulk": 0, 
       "search": 0 
      }, 
      "throttled_millis": 0, 
      "requests_per_second": -1, 
      "throttled_until_millis": 0, 
      "failures": [] 
} 

チェックのために:そうのような (response.updated == 0)場合。True =>新しいオブジェクトを安全に挿入します。 (同様の競合をチェック)ELSE

POST /test/type/ 
{ 
    "text": "some text", 
    "type": "a real type", 
    "occurences": 1 
} 

カウントが更新されたものとあなた発生しません。

このソリューションを使用すると、競合状態に陥ることがあります。これでversion_conflictsが発生します。 この問題が発生した場合、3つのことができます。

  1. キューとワーカーを使用してリクエスト後にリクエストを実行します。
  2. 単純なクエリを使用してIDを取得し、競合他社の多くの試行で数字 を指定できるupsertsを使用します。一括更新もオプションです。
  3. 使用これらのオプション:

    waitForCompletion:真、 紛争: "進む"、 リフレッシュ:これはリクエストがハングアップします

本当それが解決されるまでの応答時間がするので、より大きくて、完了とブロックを待つことになる。各インデックスの後に更新すると、データのインデックスを再作成するため、非常に悪い習慣です。これによりバージョンが更新され、バージョンの競合はなくなります。

0

newest documentationを見ると、あなたが望むことができるはずです。ドキュメントの例を次に示します。

POST twitter/_update_by_query 
{ 
    "script": { 
    "inline": "ctx._source.likes++", 
    "lang": "painless" 
    }, 
    "query": { 
    "term": { 
     "user": "kimchy" 
    } 
    } 
} 

このアプローチの欠点は、クラスタでスクリプトを有効にする必要があることです。その変更をプロダクションで行う前に、セキュリティとパフォーマンスの関係についてお読みください。

+0

私はすでにスクリプトを使用していますが、エンドポイントプライベートネットワーク内でのみ使用できます。しかし、私はそれをどうすればできるのか理解できません。つまり、見つからない場合は追加するオブジェクトをどこに置くのか、見つかった場合はどこに変更を加えるのですか? – mloureiro

関連する問題