MultiGet https://www.e-learn.cn/tag/multiget zh-hans ES系列四、ES6.3常用api之文档类api https://www.e-learn.cn/topic/3978217 <span>ES系列四、ES6.3常用api之文档类api</span> <span><span lang="" about="/user/111" typeof="schema:Person" property="schema:name" datatype="">落爺英雄遲暮</span></span> <span>2020-12-27 01:00:22</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <span id="OSC_h2_1"></span> <h2><span style="font-size: 14pt;">1.Index API: 创建并建立索引</span></h2> <div class="cnblogs_code"> <pre><code>PUT twitter/tweet/<span style="color: #800080;">1</span><span style="color: #000000;"> { </span><span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">kimchy</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">post_date</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">2009-11-15T14:12:12</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">trying out Elasticsearch</span><span style="color: #800000;">"</span><span style="color: #000000;"> }</span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html" target="_blank" rel="nofollow">Index API</a>。</p> <span id="OSC_h2_2"></span> <h2><span style="font-size: 14pt;">2.Get API: 获取文档</span></h2> <div class="cnblogs_Highlighter"> <pre class="brush:javascript;gutter:true;"><code>curl -XGET 'http://localhost:9200/twitter/tweet/1'</code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html" target="_blank" rel="nofollow">Get API</a>。</p> <span id="OSC_h2_3"></span> <h2><span style="font-size: 14pt;">3.DELETE API: 删除文档</span></h2> <div class="cnblogs_Highlighter"> <pre class="brush:javascript;gutter:true;"><code>$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1'</code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html" target="_blank" rel="nofollow">Delete API</a>。</p> <span id="OSC_h2_4"></span> <h2><span style="font-size: 14pt;">4.UPDATE API: 更新文档</span></h2> <div class="cnblogs_Highlighter"> <pre class="brush:javascript;gutter:true;"><code>PUT test/type1/1{ "counter" : 1, "tags" : ["red"]}</code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html" target="_blank" rel="nofollow">Update API</a>。</p> <span id="OSC_h2_5"></span> <h2><span style="font-size: 14pt;">5.Multi Get API: 一次批量获取文档</span></h2> <div class="cnblogs_code"> <pre><code>PUT <span style="color: #800000;">'</span><span style="color: #800000;">localhost:9200/_mget</span> <span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;"> :<br /> [ {</span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;"> } ] } </span></code></pre> </div> <p> </p> <div class="cnblogs_code"> <pre><code>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html" target="_blank" rel="nofollow">Multi Get API</a>。</code></pre> </div> <span id="OSC_h2_6"></span> <h2><span style="font-size: 14pt;">6.Bulk API: 批量操作,增删改查</span></h2> <span id="OSC_h3_7"></span> <h3>1.本地文件批量操作</h3> <div class="cnblogs_code"> <pre><code>e$ curl -s -XPOST localhost:<span style="color: #800080;">9200</span>/blog/user/_bulk --data-<span style="color: #000000;">binary @requests requests文件内容如下 {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">25</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">黎明</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">25</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">26</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">小明</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">26</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">26</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">雄安</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">27</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">28</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">笑话</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">28</span>}</code></pre> </div> <span id="OSC_h3_8"></span> <h3>2.resp 方法</h3> <div class="cnblogs_code"> <pre><code>curl -H <span style="color: #800000;">"</span><span style="color: #800000;">Content-Type: application/json</span><span style="color: #800000;">"</span> -XPOST <span style="color: #800000;">'</span><span style="color: #800000;">http://47.52.199.51:9200/book/english/_bulk</span><span style="color: #800000;">'</span> -d<span style="color: #800000;">' </span>{<span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">17</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">cddd</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">17</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">18</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">cddd</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">18</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">19</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">cddd</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">19</span><span style="color: #000000;">} {</span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>:{<span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">20</span><span style="color: #800000;">"</span><span style="color: #000000;">}} {</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">cddd</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:<span style="color: #800080;">20</span><span style="color: #000000;">} </span><span style="color: #800000;">'</span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html" rel="nofollow">Bulk API</a>。</p> <span id="OSC_h2_9"></span> <h2><span style="font-size: 14pt;">7.DELETE By Query API: 查询删除</span></h2> <div class="cnblogs_code"> <pre><code>POST /book/<span style="color: #000000;">_delete_by_query {   </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">:{     </span><span style="color: #800000;">"</span><span style="color: #800000;">match</span><span style="color: #800000;">"</span><span style="color: #000000;">:{     </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">yangxioa</span><span style="color: #800000;">"</span><span style="color: #000000;">     }   } } </span></code></pre> </div> <span id="OSC_h3_10"></span> <h3>7.1.删除所有</h3> <div class="cnblogs_code"> <pre><code>POST /book/<span style="color: #000000;">_delete_by_query { </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">match_all</span><span style="color: #800000;">"</span><span style="color: #000000;">:{} } }</span></code></pre> </div> <span id="OSC_h3_11"></span> <h3>7.2.支持路由查询(routing=XXX,匹配分片数)</h3> <div class="cnblogs_code"> <pre><code>POST twitter/_delete_by_query?routing=<span style="color: #800080;">1</span><span style="color: #000000;"> { </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">range</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">age</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">gte</span><span style="color: #800000;">"</span> : <span style="color: #800080;">10</span><span style="color: #000000;"> } } } }</span></code></pre> </div> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">took</span><span style="color: #800000;">"</span> : <span style="color: #800080;">147</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 整个操作从开始到结束的毫秒数</span> <span style="color: #800000;">"</span><span style="color: #800000;">timed_out</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">false</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> true如果在通过查询执行删除期间执行的任何请求超时 ,则将此标志设置为。</span> <span style="color: #800000;">"</span><span style="color: #800000;">total</span><span style="color: #800000;">"</span>: <span style="color: #800080;">119</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 已成功处理的文档数。</span> <span style="color: #800000;">"</span><span style="color: #800000;">deleted</span><span style="color: #800000;">"</span>: <span style="color: #800080;">119</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 已成功删除的文档数。</span> <span style="color: #800000;">"</span><span style="color: #800000;">batches</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 通过查询删除拉回的滚动响应数。</span> <span style="color: #800000;">"</span><span style="color: #800000;">version_conflicts</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 按查询删除的版本冲突数。</span> <span style="color: #800000;">"</span><span style="color: #800000;">noops</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 对于按查询删除,此字段始终等于零。它只存在,以便通过查询删除,按查询更新和reindex API返回具有相同结构的响应。</span> <span style="color: #800000;">"</span><span style="color: #800000;">retries</span><span style="color: #800000;">"</span>: { <span style="color: #008000;">//</span><span style="color: #008000;"> 通过查询删除尝试的重试次数。bulk是重试的批量操作search的数量,是重试的搜索操作的数量。</span> <span style="color: #800000;">"</span><span style="color: #800000;">bulk</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">search</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">throttled_millis</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 请求睡眠符合的毫秒数requests_per_second。</span> <span style="color: #800000;">"</span><span style="color: #800000;">requests_per_second</span><span style="color: #800000;">"</span>: -<span style="color: #800080;">1.0</span>, <span style="color: #008000;">//</span><span style="color: #008000;"> 在通过查询删除期间有效执行的每秒请求数。</span> <span style="color: #800000;">"</span><span style="color: #800000;">throttled_until_millis</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span>, <span style="color: #008000;">//</span><span style="color: #008000;">在按查询响应删除时,此字段应始终等于零。它只在使用Task API时有意义,它指示下一次(自纪元以来的毫秒数),为了符合,将再次执行受限制的请求</span> <span style="color: #800000;">"</span><span style="color: #800000;">failures</span><span style="color: #800000;">"</span><span style="color: #000000;"> : [ ] </span><span style="color: #008000;">//</span><span style="color: #008000;">如果在此过程中存在任何不可恢复的错误,则会出现故障数组。如果这是非空的,那么请求因为那些失败而中止。逐个查询是使用批处理实现的,</span> <span style="color: #000000;"> 任何故障都会导致整个进程中止,但当前批处理中的所有故障都会被收集到数组中。您可以使用该conflicts选项来防止reindex在版本冲突中中止。 }</span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html" target="_blank" rel="nofollow">Delete By Query API</a>。</p> <span id="OSC_h2_12"></span> <h2><span style="font-size: 14pt;">8.update更新api </span></h2> <span id="OSC_h3_13"></span> <h3>8.1.脚本更新</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.counter += params.count</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">lang</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span>,<span style="color: #008000;">//</span><span style="color: #008000;"> ES语言类型</span> <span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">count</span><span style="color: #800000;">"</span> : <span style="color: #800080;">4</span><span style="color: #000000;"> } } }</span></code></pre> </div> <span id="OSC_h3_14"></span> <h3>8.2.新增字段</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.new_field = 'value_of_new_field'</span><span style="color: #800000;">"</span><span style="color: #000000;"> }</span></code></pre> </div> <span id="OSC_h3_15"></span> <h3>8.3.删除字段</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.remove('new_field')</span><span style="color: #800000;">"</span><span style="color: #000000;"> }</span></code></pre> </div> <span id="OSC_h3_16"></span> <h3>8.4.存在就更新</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">lang</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">tag</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">green</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } }</span></code></pre> </div> <span id="OSC_h3_17"></span> <h3>8.5.更新部分字段</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">doc</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">new_name</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <span id="OSC_h3_18"></span> <h3>8.6.upsert:存在就更新,不存在插入</h3> <div class="cnblogs_code"> <pre><code>POST test/_doc/<span style="color: #800080;">1</span>/<span style="color: #000000;">_update { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.counter += params.count</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">lang</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">params</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">count</span><span style="color: #800000;">"</span> : <span style="color: #800080;">4</span><span style="color: #000000;"> } }, </span><span style="color: #800000;">"</span><span style="color: #800000;">upsert</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">counter</span><span style="color: #800000;">"</span> : <span style="color: #800080;">1</span><span style="color: #000000;"> } }</span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html" rel="nofollow">Update 脚本更新API</a></p> <span id="OSC_h2_19"></span> <h2>9.UPDATE BY QUERY API:查询更新</h2> <span id="OSC_h3_20"></span> <h3>9.1.更新,重新索引</h3> <div class="cnblogs_code"> <pre><code>POST twitter/_update_by_query?conflicts=proceed</code></pre> </div> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">took</span><span style="color: #800000;">"</span> : <span style="color: #800080;">147</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">timed_out</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">false</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">updated</span><span style="color: #800000;">"</span>: <span style="color: #800080;">120</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">deleted</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">batches</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">version_conflicts</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">noops</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">retries</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">bulk</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">search</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">throttled_millis</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">requests_per_second</span><span style="color: #800000;">"</span>: -<span style="color: #800080;">1.0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">throttled_until_millis</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">total</span><span style="color: #800000;">"</span>: <span style="color: #800080;">120</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">failures</span><span style="color: #800000;">"</span><span style="color: #000000;"> : [ ] }</span></code></pre> </div> <p><span>ES内部自带实现乐观锁控制,先查询出要更新的记录的版本号,更新时匹配版本号时候一致。<br />所有更新和查询失败都会导致</span><code class="literal">_update_by_query</code><span>中止并</span><code class="literal">failures</code><span><span>在响应</span><span>中返回</span><span>。</span><span>已执行的更新仍然存在。</span><span>换句话说,该过程不会回滚,只会中止。</span><span><span style="color: #ff0000;">当第一个失败导致中止时</span>,失败的批量请求返回的所有失败都将在</span></span><code class="literal">failures</code><span><span>元素</span><span>中返回</span><span>; </span><span>因此,可能存在相当多的失败实体。</span></span></p> <p><span style="color: #ff0000;">如果您只想计算版本冲突,不要导致<code class="literal">_update_by_query</code></span><span><span style="color: #ff0000;"> 中止</span>,您可以</span><code class="literal">conflicts=proceed</code><span>在URL或</span><code class="literal">"conflicts": "proceed",改配置当第一个冲突时会会继续执行,</code>version_conflicts冲突数量。</p> <span id="OSC_h3_21"></span> <h3>9.2.查询更新</h3> <div class="cnblogs_code"> <pre><code>POST twitter/_update_by_query?conflicts=<span style="color: #000000;">proceed { </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">kimchy</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } }</span></code></pre> </div> <span id="OSC_h3_22"></span> <h3>9.3.查询脚本更新</h3> <div class="cnblogs_code"> <pre><code>POST twitter/<span style="color: #000000;">_update_by_query { </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.likes++</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">lang</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">kimchy</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } }</span></code></pre> </div> <p>也可以同时在多个索引和多个类型上完成这一切,就像搜索API一样:</p> <div class="cnblogs_code"> <pre><code>POST twitter,blog / _doc,post / _update_by_query</code></pre> </div> <p><code class="literal">routing</code><span><span>则路由将复制到滚动查询,将进程限制为与该路由值匹配的分片:</span></span></p> <div class="cnblogs_code"> <pre><code>POST twitter/_update_by_query?routing=<span style="color: #800080;">1</span></code></pre> </div> <p><span><span>默认情况下,</span></span><code class="literal">_update_by_query</code><span><span>使用1000的滚动批次。可以使用</span></span><code class="literal">scroll_size</code><span><span>URL参数</span><span>更改批量大小</span><span>:</span></span></p> <div class="cnblogs_code"> <pre><code>POST twitter/_update_by_query?scroll_size=<span style="color: #800080;">100</span></code></pre> </div> <span id="OSC_h3_23"></span> <h3>9.4.使用TASK API获取所有正在运行的逐个查询请求的状态</h3> <div class="cnblogs_code"> <pre><code>GET _tasks?detailed=<span style="color: #0000ff;">true</span>&amp;actions=*<span style="color: #000000;">byquery<br /></span></code></pre> </div> <p>结果:</p> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">nodes</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">r1A2WoRbTwKZ516z6NEs5A</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">r1A2WoR</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">transport_address</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">127.0.0.1:9300</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">host</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">127.0.0.1</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">ip</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">127.0.0.1:9300</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">attributes</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">testattr</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">portsfile</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">true</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">tasks</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">r1A2WoRbTwKZ516z6NEs5A:36619</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">node</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">r1A2WoRbTwKZ516z6NEs5A</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span> : <span style="color: #800080;">36619</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">transport</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">action</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">indices:data/write/update/byquery</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">status</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">total</span><span style="color: #800000;">"</span> : <span style="color: #800080;">6154</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">updated</span><span style="color: #800000;">"</span> : <span style="color: #800080;">3500</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">created</span><span style="color: #800000;">"</span> : <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">deleted</span><span style="color: #800000;">"</span> : <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">batches</span><span style="color: #800000;">"</span> : <span style="color: #800080;">4</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">version_conflicts</span><span style="color: #800000;">"</span> : <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">noops</span><span style="color: #800000;">"</span> : <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">retries</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">bulk</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">search</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;"> } </span><span style="color: #800000;">"</span><span style="color: #800000;">throttled_millis</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">description</span><span style="color: #800000;">"</span> : <span style="color: #800000;">""</span><span style="color: #000000;"> } } } } }</span></code></pre> </div> <p>使用任务ID,您可以直接查找任务:</p> <div class="cnblogs_code"> <pre><code>GET /_tasks/taskId:<span style="color: #800080;">1</span></code></pre> </div> <p><span><span>可以使用</span></span><span><span>任务取消API</span></span><span><span>取消任何按查询更新</span><span>:</span></span></p> <div class="cnblogs_code"> <pre><code>POST _tasks/task_id:<span style="color: #800080;">1</span>/_cancel</code></pre> </div> <p>手动切片:</p> <div class="cnblogs_code"> <pre><code>POST twitter/<span style="color: #000000;">_update_by_query { </span><span style="color: #800000;">"</span><span style="color: #800000;">slice</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">max</span><span style="color: #800000;">"</span>: <span style="color: #800080;">2</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source['extra'] = 'test'</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html" target="_parent" rel="nofollow">Update By Query API</a></p> <span id="OSC_h2_24"></span> <h2><span style="font-size: 14pt;">10.Reindex API:重新索引</span></h2> <span id="OSC_h3_25"></span> <h3>10.1.复制整个索引</h3> <p><span><span>最基本的形式</span></span><code class="literal">_reindex</code><span><span>只是将文档从一个索引复制到另一个索引。</span><span>这会将</span></span><code class="literal">twitter</code><span><span>索引中的</span><span>文档复制</span><span>到</span></span><code class="literal">new_twitter</code><span><span>索引中(<span style="color: #ff0000;">前提是要有相同的索引类型</span>):</span></span></p> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">twitter</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">new_twitter</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <span id="OSC_h3_26"></span> <h3>10.2.复制匹配的文档</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">twitter</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">_doc</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">kimchy</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">new_twitter</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <span id="OSC_h3_27"></span> <h3>10.3.复制多个索引文档</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex<br />{<br />  "source": {<br />    "index": ["book", "blog"],<br />    "type": ["english", "user"]<br />  },<br />  "dest": {<br />    "index": "book1"<br />  }<br /> } </span></code></pre> </div> <p> ES 6.3只支持一个索引一个类型,所以上面这个并没有实验成功!提示:</p> <div class="cnblogs_code"> <pre><code><span style="color: #800000;">"</span><span style="color: #800000;">reason</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">Rejecting mapping update to [book1] as the final mapping would have more than 1 type: [english, user]</span><span style="color: #800000;">"</span></code></pre> </div> <span id="OSC_h3_28"></span> <h3>10.4.是否覆盖版本号</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST reindex <br />{ </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book1</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">version_type</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">external</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p><span style="color: #ff0000;">“external”:表示使用<span>source的版本号覆盖dest的版本号,当source的版本号&lt;=dest的版本号会提示冲突,“internal”:表示保持dest的版本号自增。</span></span></p> <span id="OSC_h3_29"></span> <h3><span style="color: #ff0000;"><span><span style="color: #333300;">10.5.只复制不存在的记录,已经存在的记录提示冲突</span></span></span></h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book1</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">op_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">create</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p><span style="color: #444444;">默认情况下,版本冲突会中止该</span><code class="literal"><span style="font-size: medium;">_reindex</span></code><span><span>过程,但可以通过</span></span><code class="literal"><span style="font-size: medium;">"conflicts": "proceed"</span></code><span><span>请求正文中的</span><span>设置</span><span>对</span><span>它们进行计数</span></span></p> <span id="OSC_h3_30"></span> <h3>10.6.排序复制指定数量</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex<br />{ </span><span style="color: #800000;">"</span><span style="color: #800000;">size</span><span style="color: #800000;">"</span>:<span style="color: #800080;">10</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">sort</span><span style="color: #800000;">"</span>: { <span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">desc</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book1</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">op_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">create</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p>如果报错禁止排序:<span style="color: #ff0000;">Fielddata is disabled on text fields by...</span></p> <p>聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启:</p> <div class="cnblogs_code"> <pre><code>PUT book/_mapping/<span style="color: #000000;">english { </span><span style="color: #800000;">"</span><span style="color: #800000;">properties</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">fielddata</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;"> } } }</span></code></pre> </div> <span id="OSC_h3_31"></span> <h3> 10.7.复制部分字段</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex {</span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_source</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">age</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book1</span><span style="color: #800000;">"</span><span style="color: #000000;"> }</span><span style="color: #000000;"> }</span></code></pre> </div> <span id="OSC_h3_32"></span> <h3>10.8.过滤修改元数据再复制</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex</span></code></pre> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">size</span><span style="color: #800000;">"</span>:<span style="color: #800080;">2</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_source</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">age</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book1</span><span style="color: #800000;">",<br /> "routing": "=age" // 根据age进行路由<br /></span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">script</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">if (ctx._source.age == 12) {ctx._source.age++}</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">lang</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p><span>就像在</span><code class="literal">_update_by_query</code><span>,您可以设置</span><code class="literal">ctx.op</code><span>更改在目标索引上执行的操作:</span></p> <div class="variablelist"> <dl><dt> <span><code class="literal">noop</code></span> </dt> <dd> <span>设置</span> <code class="literal">ctx.op = "noop"</code> <span><span>脚本是否确定不必在目标索引中编制索引。</span><span>这种无操作将</span></span> <code class="literal">noop</code> <span>在</span> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html#docs-reindex-response-body" rel="nofollow">响应机构</a> <span><span>的</span><span>计数器中</span><span>报告</span><span>。</span></span> </dd> <dt> <span><code class="literal">delete</code></span> </dt> <dd> <code class="literal">ctx.op = "delete"</code> <span><span>如果脚本确定必须从目标索引中删除文档,请进行</span><span> 设置</span></span> <span><span> </span><span>。</span></span> </dd> </dl></div> <span id="OSC_h3_33"></span> <h3><span style="color: #333333;"><span> 10.9.从远程复制</span></span></h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">POST _reindex { </span><span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">remote</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">host</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">http://otherhost:9200</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">username</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">password</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">pass</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">source</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">query</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">match</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">data</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } }, </span><span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">dest</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <span id="OSC_h3_34"></span> <h3><span> 10.10.查看重建索引任务</span></h3> <div class="cnblogs_code"> <pre><code>GET _tasks?detailed=<span style="color: #0000ff;">true</span>&amp;actions=*reindex</code></pre> </div> <p><span style="font-size: 15px;">官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html" target="_blank" rel="nofollow">Reindex  API</a></span></p> <span id="OSC_h2_35"></span> <h2><span style="font-size: 14pt;"><strong>11.term Vectors:</strong>分词api</span></h2> <span id="OSC_h3_36"></span> <h3>11.1. term的基本信息</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;"># term_freq:在在该字段中的频率 # position:词在该字段中的位置 # start_offset:从什么偏移量开始的 # end_offset: 到什么偏移量结束</span></code></pre> </div> <p> </p> <span id="OSC_h3_37"></span> <h3>11.2 term的统计信息</h3> <p>如果启用了term的统计信息,即term_statistics设为true,那么有哪些统计信息呢?</p> <div class="cnblogs_code"> <pre><code><span style="color: #000000;"># doc_freq: 该词在文档中出现的频率 # ttf:total term frequency的缩写,一个term在所有document中出现的频率</span><a name="t2" rel="nofollow" id="t2"></a></code></pre> </div> <span id="OSC_h3_38"></span> <h3>11.3字段的统计信息</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">如果启用了字段统计信息,即field_statistics设为true,那么有哪些统计信息呢? # sum_doc_freq: 一个字段中所有term的文档频率之和 # doc_count: 有多少个文档包含这个字段 # sum_ttf:sum total term frequency的缩写,一个字段中的每一个term的在所有文档出现之和 term statistics和field statistics并不精准,不会被考虑有的doc可能被删除了</span></code></pre> </div> <span id="OSC_h3_39"></span> <h3>11.5采集term信息的方式</h3> <p>采集term信息的方式有两种:index-time(从已经存储的索引中查看) 和 query-time(及时生成)</p> <span id="OSC_h3_40"></span> <h3>11.6 index-time方式</h3> <p>需要在mapping配置一下,然后建立索引的时候,就直接生成这些词条和文档的统计信息</p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/0200a70fb91216ed2f665f25eedf4e32462.jpg" data-original="https://oscimg.oschina.net/oscnet/0200a70fb91216ed2f665f25eedf4e32462.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/10fd0698a07065778fdc3681e75dcebb701.jpg" data-original="https://oscimg.oschina.net/oscnet/10fd0698a07065778fdc3681e75dcebb701.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code>PUT /<span style="color: #000000;">website { </span><span style="color: #800000;">"</span><span style="color: #800000;">mappings</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">article</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">properties</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_vector</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">with_positions_offsets</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">store</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">true</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">analyzer</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">fulltext</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } } }, </span><span style="color: #800000;">"</span><span style="color: #800000;">settings</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">analysis</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">analyzer</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">fulltext</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">custom</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokenizer</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">whitespace</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">filter</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ </span><span style="color: #800000;">"</span><span style="color: #800000;">lowercase</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">type_as_payload</span><span style="color: #800000;">"</span><span style="color: #000000;"> ] } } } } }</span></code></pre> </div> <span>View Code</span> </div> <p> </p> <span id="OSC_h3_41"></span> <h3>11.7 query-time方式</h3> <p>即之前没有在mapping里配置过,而是通过查询的方式产生这些统计信息</p> <div class="cnblogs_code"> <pre><code>POST /ecommerce/music/<span style="color: #800080;">1</span>/<span style="color: #000000;">_termvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>:[<span style="color: #800000;">"</span><span style="color: #800000;">desc</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">offsets</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">payloads</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">positions</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span> : <span style="color: #0000ff;">true</span><span style="color: #000000;"> }</span></code></pre> </div> <p> </p> <span id="OSC_h3_42"></span> <h3><strong>11.8 手动指定analyzer来生成termvector</strong></h3> <p>我么可以通过指定per_field_analyzer设置一个分词器对该字段文本进行分词。</p> <div class="cnblogs_code"> <pre><code>POST /ecommerce/music/<span style="color: #800080;">1</span>/<span style="color: #000000;">_termvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>:[<span style="color: #800000;">"</span><span style="color: #800000;">desc</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">offsets</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">payloads</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">positions</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span> : <span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">per_field_analyzer</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">standard</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <span id="OSC_h3_43"></span> <h3><strong>11.9 在线文档及时生成termvector</strong></h3> <div class="cnblogs_code"> <pre><code>POST book/english/<span style="color: #000000;">_termvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">doc</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">hellow word</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">text</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">twitter test test test</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">per_field_analyzer</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">standard</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }</span></code></pre> </div> <p><strong>response</strong></p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/e4c6ebe49e20720d5d8dfda7670f947f2d8.jpg" data-original="https://oscimg.oschina.net/oscnet/e4c6ebe49e20720d5d8dfda7670f947f2d8.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/4dde84ea1fffa739e019da9b5e54e574ae8.jpg" data-original="https://oscimg.oschina.net/oscnet/4dde84ea1fffa739e019da9b5e54e574ae8.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_version</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">found</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">took</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_vectors</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_doc_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">632</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">doc_count</span><span style="color: #800000;">"</span>: <span style="color: #800080;">30</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_ttf</span><span style="color: #800000;">"</span>: <span style="color: #800080;">991</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">terms</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">hellow</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">6</span><span style="color: #000000;"> } ] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">word</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">7</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">11</span><span style="color: #000000;"> } ] } } } } }</span></code></pre> </div> <span>View Code</span> </div> <span id="OSC_h3_44"></span> <h3>11.10 term的统计信息</h3> <p>我们可以根据term的统计信息,过滤出我么想看的统计结果,比如过滤掉一些出现频率过低的term,比如我要过滤出该字段最多只有10个term,而且那些term在该字段中出现的频率为2,且</p> <div class="cnblogs_code"> <pre><code>POST /ecommerce/music/<span style="color: #800080;">1</span>/<span style="color: #000000;">_termvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>:[<span style="color: #800000;">"</span><span style="color: #800000;">desc</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">offsets</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">payloads</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">positions</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>:<span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span> : <span style="color: #0000ff;">true</span><span style="color: #000000;">,<br /></span><span style="color: #800000;">"</span><span style="color: #800000;">filter</span><span style="color: #800000;">"</span><span style="color: #000000;">:{ </span><span style="color: #800000;">"</span><span style="color: #800000;">max_num_terms</span><span style="color: #800000;">"</span>:<span style="color: #800080;">10</span><span style="color: #000000;">, // 返回的最大分词输 </span><span style="color: #800000;">"</span><span style="color: #800000;">min_term_freq</span><span style="color: #800000;">"</span> : <span style="color: #800080;">2</span><span style="color: #000000;">, // 忽略低于源文档中出现的次数 </span><span style="color: #800000;">"</span><span style="color: #800000;">min_doc_freq</span><span style="color: #800000;">"</span> : <span style="color: #800080;">1 // 忽略低于所有文档中出现的次数</span><span style="color: #000000;"> }<br /> }</span></code></pre> </div> <span id="OSC_h3_45"></span> <h3>11.11 term过滤参数说明</h3> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">max_num_terms:每个字段必须返回的最大分词数。默认为25。 min_term_freq:忽略源文档中低于此频率的单词。默认为1。 max_term_freq:忽略源文档中超过此频率的单词。默认为无限制。 min_doc_freq:忽略至少在这么多文档中没有出现的分词。默认为1。 max_doc_freq:忽略超过这么多文档中出现的单词。默认为无限制。 min_word_length:最小字长,低于该字长将被忽略。默认为0。 max_word_length:最大字长,高于该字长将被忽略。默认为unbounded(</span><span style="color: #800080;">0</span>)。</code></pre> </div> <p> 官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-termvectors.html" target="_blank" rel="nofollow">Term Vector A</a>pi</p> <span id="OSC_h2_46"></span> <h2><span style="font-size: 14pt;">12 批量返回分词:Multi termvectors API</span></h2> <p>采集term信息的方式有两种:index-time(从已经存储的索引中查看) 和 query-time(及时生成)</p> <span id="OSC_h3_47"></span> <h3>12.1 index-time</h3> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/2b1b48ee4e24cb1a60fb3af4b45f86b2631.jpg" data-original="https://oscimg.oschina.net/oscnet/2b1b48ee4e24cb1a60fb3af4b45f86b2631.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/043971cd99239801d92b89bc54fcc863117.jpg" data-original="https://oscimg.oschina.net/oscnet/043971cd99239801d92b89bc54fcc863117.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code>POST /<span style="color: #000000;">_mtermvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">twitter</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">_doc</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;"> }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">twitter</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">_doc</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span><span style="color: #000000;"> ] } ] }</span></code></pre> </div> <span>View Code</span> </div> <p>url中指定索引:</p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/33b7efb40cc6e01b45d90d83e2e801cb857.jpg" data-original="https://oscimg.oschina.net/oscnet/33b7efb40cc6e01b45d90d83e2e801cb857.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/0f6a885af8f4cb79bba9a6be427fda24220.jpg" data-original="https://oscimg.oschina.net/oscnet/0f6a885af8f4cb79bba9a6be427fda24220.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code>POST /twitter/<span style="color: #000000;">_mtermvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">_doc</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span><span style="color: #000000;"> ], </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;"> }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">_doc</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;"> } ] }</span></code></pre> </div> <span>View Code</span> </div> <p>url中指定索引类型:</p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/103b9a9a85a8c31ff246970d04160030619.jpg" data-original="https://oscimg.oschina.net/oscnet/103b9a9a85a8c31ff246970d04160030619.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/19c855d636e1b182e39781daff73a4e334e.jpg" data-original="https://oscimg.oschina.net/oscnet/19c855d636e1b182e39781daff73a4e334e.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code>POST /twitter/_doc/<span style="color: #000000;">_mtermvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span><span style="color: #000000;"> ], </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;"> }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_id</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;"> } ] }</span></code></pre> </div> <span>View Code</span> </div> <p>如果索引类型和字段都相同:</p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/b27a7c96356d969b983987af9c7872a2413.jpg" data-original="https://oscimg.oschina.net/oscnet/b27a7c96356d969b983987af9c7872a2413.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/ba37e76eedbc0cf3689e8f71d88d9a4e5d7.jpg" data-original="https://oscimg.oschina.net/oscnet/ba37e76eedbc0cf3689e8f71d88d9a4e5d7.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code>POST /twitter/_doc/<span style="color: #000000;">_mtermvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">ids</span><span style="color: #800000;">"</span> : [<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">parameters</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span><span style="color: #000000;"> ], </span><span style="color: #800000;">"</span><span style="color: #800000;">term_statistics</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;"> } }</span></code></pre> </div> <span>View Code</span> </div> <span id="OSC_h3_48"></span> <h3><span style="font-size: 14px;">12.2及时批量生成<br /></span></h3> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/8e98be1e29075c242b88d504bb20ee038a2.jpg" data-original="https://oscimg.oschina.net/oscnet/8e98be1e29075c242b88d504bb20ee038a2.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/99f810ce697a8242665ba40d6ebc5036fd3.jpg" data-original="https://oscimg.oschina.net/oscnet/99f810ce697a8242665ba40d6ebc5036fd3.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code><span style="color: #000000;">POST_mtermvectors { </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">doc</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">John Doe</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">twitter test test test</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">per_field_analyzer</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">standard</span><span style="color: #800000;">"</span><span style="color: #000000;"> } }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">doc</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">Jane Doe</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">message</span><span style="color: #800000;">"</span> : <span style="color: #800000;">"</span><span style="color: #800000;">Another twitter test ...</span><span style="color: #800000;">"</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">fields</span><span style="color: #800000;">"</span>: [<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">], </span><span style="color: #800000;">"</span><span style="color: #800000;">per_field_analyzer</span><span style="color: #800000;">"</span><span style="color: #000000;"> : { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">standard</span><span style="color: #800000;">"</span><span style="color: #000000;"> } } ] }</span></code></pre> </div> <span>View Code</span> </div> <p><strong>response:</strong></p> <div class="cnblogs_code"> <img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/89de42c9b408851d15284a473d76657539e.jpg" data-original="https://oscimg.oschina.net/oscnet/89de42c9b408851d15284a473d76657539e.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img alt="" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/b4613f43550cdb290b2ce1343ba900e0db1.jpg" data-original="https://oscimg.oschina.net/oscnet/b4613f43550cdb290b2ce1343ba900e0db1.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div class="cnblogs_code_hide"> <pre><code><span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">docs</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_version</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">found</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">took</span><span style="color: #800000;">"</span>: <span style="color: #800080;">2</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_vectors</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_doc_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">632</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">doc_count</span><span style="color: #800000;">"</span>: <span style="color: #800080;">30</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_ttf</span><span style="color: #800000;">"</span>: <span style="color: #800080;">991</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">terms</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">doe</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">5</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">8</span><span style="color: #000000;"> } ] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">john</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">4</span><span style="color: #000000;"> } ] } } } } }, { </span><span style="color: #800000;">"</span><span style="color: #800000;">_index</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">book</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">english</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">_version</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">found</span><span style="color: #800000;">"</span>: <span style="color: #0000ff;">true</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">took</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">term_vectors</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">field_statistics</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_doc_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">632</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">doc_count</span><span style="color: #800000;">"</span>: <span style="color: #800080;">30</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">sum_ttf</span><span style="color: #800000;">"</span>: <span style="color: #800080;">991</span><span style="color: #000000;"> }, </span><span style="color: #800000;">"</span><span style="color: #800000;">terms</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">doe</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">5</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">8</span><span style="color: #000000;"> } ] }, </span><span style="color: #800000;">"</span><span style="color: #800000;">jane</span><span style="color: #800000;">"</span><span style="color: #000000;">: { </span><span style="color: #800000;">"</span><span style="color: #800000;">term_freq</span><span style="color: #800000;">"</span>: <span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">tokens</span><span style="color: #800000;">"</span><span style="color: #000000;">: [ { </span><span style="color: #800000;">"</span><span style="color: #800000;">position</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">start_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">0</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">end_offset</span><span style="color: #800000;">"</span>: <span style="color: #800080;">4</span><span style="color: #000000;"> } ] } } } } } ] }</span></code></pre> </div> <span>View Code</span> </div> <span id="OSC_h3_49"></span> <h3>12.2.返回该索引全部文档的分词统计</h3> <div class="cnblogs_code"> <pre><code><span>POST book/_search<br />{ <span>"<span>size<span>" : <span>0<span>, <span>"<span>aggs<span>"<span> : { <span>"<span>messages<span>"<span> : { <span>"<span>terms<span>"<span> : { <span>"<span>size<span>" : <span>10<span>, <span>"<span>field<span>" : <span>"<span>name<span>"<span> } } } }</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre> </div> <p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-termvectors.html" target="_blank" rel="nofollow">Multi termvectors API</a></p> <span id="OSC_h2_50"></span> <h2>13.?refresh</h2> <p>ES的索引数据是写入到磁盘上的。但这个过程是分阶段实现的,因为IO的操作是比较费时的。</p> <ol><li>先写到内存中,此时不可搜索</li> <li>默认经过 1s 之后会(refresh)被写入 lucene 的底层文件 segment 中 ,此时可以搜索到</li> <li>flush之后才会写入磁盘</li> </ol><p>以上过程由于随时可能被中断导致数据丢失,所以每一个过程都会有 translog 记录,如果中间有任何一步失败了,等服务器重启之后就会重试,保证数据写入。translog也是先存在内存里的,然后默认5秒刷一次写到硬盘里。</p> <p>在 index ,Update , Delete , Bulk 等操作中,可以设置 refresh 的值。取值如下:</p> <span id="OSC_h3_51"></span> <h3><code>13.1.refresh=true</code> </h3> <p>更新数据之后,立刻对相关的分片(包括副本) 刷新,这个刷新操作保证了数据更新的结果可以立刻被搜索到。</p> <span id="OSC_h3_52"></span> <h3><code>13.2.refresh=wait_for</code> </h3> <p>这个参数表示,刷新后返回。刷新不会立刻进行,而是等待一段时间才刷新 ( <code>index.refresh_interval</code>),默认时间是 1 秒。刷新时间间隔可以通过index 的配置动态修改。或者直接手动刷新 <code>POST /twitter/_refresh</code></p> <span id="OSC_h3_53"></span> <h3><code>13.3.refresh=false</code></h3> <p>refresh 的默认值,立即返回。更新数据之后不立刻刷新,在返回结果之后的某个时间点会自动刷新,也就是随机的,看es服务器的运行情况。</p> <p>那么选择哪种刷新方式?</p> <ol><li> <p>wait_for 和 true 对比,前者每次会积累一定的工作量再去刷新</p> </li> <li> <p>true 是低效的,因为每次实时刷新会产生很小的 segment,随后这些零碎的小段会被合并到效率更高的大 segment 中。也就是说使用 true 的代价在于,在 index 阶段会创建这些小的 segment,在搜索的时候也是搜索这些小的 segment,在合并的时候去将小的 segment 合并到大的 segment 中</p> </li> <li> <p>不要在多个请求中对每一条数据都设置 <code>refresh=wait_for</code> , 用bulk 去批量更新,然后在单个的请求中设置 <code>refresh=wait_for</code> 会好一些</p> </li> <li> <p>如果 <code>index.refresh_interval: -1</code> ,将会禁用刷新,那带上了 <code>refresh=wait_for</code> 参数的请求实际上刷新的时间是未知的。如果 <code>index.refresh_interval</code> 的值设置的比默认值( 1s )更小,比如 200 ms,那带上了 <code>refresh=wait_for</code> 参数的请求将很快刷新,但是仍然会产生一些低效的segment。</p> </li> <li> <p><code>refresh=wait_for</code> 只会影响到当前需要强制刷新的请求,<code>refresh=true</code> 却会影响正在处理的其他请求。所以如果想尽可能小的缩小影响范围时,应该用 <code>refresh=wait_for</code></p> </li> </ol><p>官方文档参考:<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html" target="_blank" rel="nofollow">Refresh api</a></p> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/4301507/blog/3878185</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/curl" hreflang="zh-hans">curl</a></div> <div class="field--item"><a href="/tag/nes" hreflang="zh-hans">nes</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/mindoc" hreflang="zh-hans">MinDoc</a></div> </div> </div> Sat, 26 Dec 2020 17:00:22 +0000 落爺英雄遲暮 3978217 at https://www.e-learn.cn RedisTemplate常用集合使用说明-opsForHash(四) https://www.e-learn.cn/topic/3755914 <span>RedisTemplate常用集合使用说明-opsForHash(四)</span> <span><span lang="" about="/user/33" typeof="schema:Person" property="schema:name" datatype="">被刻印的时光 ゝ</span></span> <span>2020-08-14 12:06:47</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <span id="OSC_h2_1"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>1、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#put-H-HK-HV-" rel="nofollow">put</a><code>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key,</code> <code><a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a> hashKey,</code> <code><a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HV</a> value)</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>   新增hashMap值。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>   </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">redisTemplate.opsForHash().put(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map1-1"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">redisTemplate.opsForHash().put(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map2"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map2-2"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_2"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>2、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#values-H-" rel="nofollow">values</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>  获取指定变量中的hashMap值。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">List&lt;Object&gt; hashList = redisTemplate.opsForHash().values(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过values(H key)方法获取变量中的hashMap值:"</span></span></span></span></span></span></span> + hashList);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_3"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>3、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#entries-H-" rel="nofollow">entries</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>  获取变量中的键值对。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Map&lt;Object,Object&gt; map = redisTemplate.opsForHash().entries(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过entries(H key)方法获取变量中的键值对:"</span></span></span></span></span></span></span> + map);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_4"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>4、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#get-H-java.lang.Object-" rel="nofollow">get</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="https://docs.oracle.com/javase/6/docs/api/java/lang/Object.html?is-external=true" rel="nofollow">Object</a> hashKey)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>  获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Object mapValue = redisTemplate.opsForHash().get(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过get(H key, Object hashKey)方法获取map键的值:"</span></span></span></span></span></span></span> + mapValue);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_5"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>5、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#hasKey-H-java.lang.Object-" rel="nofollow">hasKey</a><code>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key,</code> <code><a href="https://docs.oracle.com/javase/6/docs/api/java/lang/Object.html?is-external=true" rel="nofollow">Object</a> hashKey)</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>      判断变量中是否有指定的map键。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a626a4"><span>boolean</span></span></span></span></span></span></span> hashKeyBoolean = redisTemplate.opsForHash().hasKey(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map3"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过hasKey(H key, Object hashKey)方法判断变量中是否存在map键:"</span></span></span></span></span></span></span> + hashKeyBoolean);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_6"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>6、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#keys-H-" rel="nofollow">keys</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>       获取变量中的键。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Set&lt;Object&gt; keySet = redisTemplate.opsForHash().keys(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过keys(H key)方法获取变量中的键:"</span></span></span></span></span></span></span> + keySet);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_7"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>7、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#size-H-" rel="nofollow">size</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>        获取变量的长度。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a626a4"><span>long</span></span></span></span></span></span></span> hashLength = redisTemplate.opsForHash().size(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过size(H key)方法获取变量的长度:"</span></span></span></span></span></span></span> + hashLength);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_8"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>8、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#increment-H-HK-double-" rel="nofollow">increment</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a> hashKey, double delta)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>       使变量中的键以double值的大小进行自增长。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a626a4"><span>double</span></span></span></span></span></span></span> hashIncDouble = redisTemplate.opsForHash().increment(<span><span><span><span><span><span style="color:#50a14f"><span>"hashInc"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#986801"><span>3</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过increment(H key, HK hashKey, double delta)方法使变量中的键以值的大小进行自增长:"</span></span></span></span></span></span></span> + hashIncDouble);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_9"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>9、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#increment-H-HK-long-" rel="nofollow">increment</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a> hashKey, long delta)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p style="text-align:start"><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>使变量中的键以long值的大小进行自增长。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a626a4"><span>long</span></span></span></span></span></span></span> hashIncLong = redisTemplate.opsForHash().increment(<span><span><span><span><span><span style="color:#50a14f"><span>"hashInc"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map2"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#986801"><span>6</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过increment(H key, HK hashKey, long delta)方法使变量中的键以值的大小进行自增长:"</span></span></span></span></span></span></span> + hashIncLong);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_10"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>10、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#multiGet-H-java.util.Collection-" rel="nofollow">multiGet</a><code>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key,</code> <code><a href="https://docs.oracle.com/javase/6/docs/api/java/util/Collection.html?is-external=true" rel="nofollow">Collection</a>&lt;<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a>&gt; hashKeys)</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>         以集合的方式获取变量中的值。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">List&lt;Object&gt; list = <span><span><span><span><span><span style="color:#a626a4"><span>new</span></span></span></span></span></span></span> ArrayList&lt;Object&gt;();</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">list.add(<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">list.add(<span><span><span><span><span><span style="color:#50a14f"><span>"map2"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">List mapValueList = redisTemplate.opsForHash().multiGet(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,list);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过multiGet(H key, Collection&lt;HK&gt; hashKeys)方法以集合的方式获取变量中的值:"</span></span></span></span></span></span></span>+mapValueList);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_11"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> 11、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#putAll-H-java.util.Map-" rel="nofollow">putAll</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="https://docs.oracle.com/javase/6/docs/api/java/util/Map.html?is-external=true" rel="nofollow">Map</a>&lt;? extends <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a>,? extends <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HV</a>&gt; m)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>   以map集合的形式添加键值对。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Map newMap = <span><span><span><span><span><span style="color:#a626a4"><span>new</span></span></span></span></span></span></span> HashMap();</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">newMap.put(<span><span><span><span><span><span style="color:#50a14f"><span>"map3"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map3-3"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">newMap.put(<span><span><span><span><span><span style="color:#50a14f"><span>"map5"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map5-5"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">redisTemplate.opsForHash().putAll(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,newMap);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">map = redisTemplate.opsForHash().entries(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过putAll(H key, Map&lt;? extends HK,? extends HV&gt; m)方法以map集合的形式添加键值对:"</span></span></span></span></span></span></span> + map);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_12"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>12、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#putIfAbsent-H-HK-HV-" rel="nofollow">putIfAbsent</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HK</a> hashKey, <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">HV</a> value)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>          如果变量值存在,在变量中可以添加不存在的的键值对,如果变量不存在,则新增一个变量,同时将键值对添加到该变量。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">redisTemplate.opsForHash().putIfAbsent(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map6"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map6-6"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">map = redisTemplate.opsForHash().entries(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过putIfAbsent(H key, HK hashKey, HV value)方法添加不存在于变量中的键值对:"</span></span></span></span></span></span></span> + map);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_13"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>13、<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#scan-H-org.springframework.data.redis.core.ScanOptions-" rel="nofollow">scan</a>(<a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow">H</a> key, <a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/ScanOptions.html" rel="nofollow">ScanOptions</a> options)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p style="text-align:start"><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>            <span><span><span><span><span><span>匹配获取键值对,</span></span></span></span></span></span><span><span><span><span><span><span><em>ScanOptions.NONE</em></span></span></span></span></span></span><span><span><span><span><span><span>为获取全部键对,</span></span></span></span></span></span><span><span><span><span><span><span><em>ScanOptions.scanOptions().match("map1").build()     </em></span></span></span></span></span></span><span><span><span><span><span><span>匹配获取键位</span></span></span></span></span></span><span><span><span><span><span><span><em>map1</em></span></span></span></span></span></span><span><span><span><span><span><span>的键值对</span></span></span></span></span></span><span><span><span><span><span><span><em>,</em></span></span></span></span></span></span><span><span><span><span><span><span>不能模糊匹配。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Cursor&lt;Map.Entry&lt;Object,Object&gt;&gt; cursor = redisTemplate.opsForHash().scan(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,ScanOptions.scanOptions().match(<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>).build());</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a0a1a7"><em><span>//Cursor&lt;Map.Entry&lt;Object,Object&gt;&gt; cursor = redisTemplate.opsForHash().scan("hashValue",ScanOptions.NONE);</span></em></span></span></span></span></span></span></code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java"><span><span><span><span><span><span style="color:#a626a4"><span>while</span></span></span></span></span></span></span> (cursor.hasNext()){</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">Map.Entry&lt;Object,Object&gt; entry = cursor.next();</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过scan(H key, ScanOptions options)方法获取匹配键值对:"</span></span></span></span></span></span></span> + entry.getKey() + <span><span><span><span><span><span style="color:#50a14f"><span>"----&gt;"</span></span></span></span></span></span></span> + entry.getValue());</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">}</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> </ol><span id="OSC_h2_14"></span> <h2><span><span><span><strong><span><span style="color:#4f4f4f"><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span><span><span><span><span><span><span><em>14</em></span></span></span></span></span></span><span><span><span><span><span><span>、</span></span></span></span></span></span><span><span><span><span><span><span><span><span><span><span><span><em><span style="color:#353833"><a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html#delete-H-java.lang.Object...-" rel="nofollow"><span><span><span><span><span><span style="color:#4a6782">delete</span></span></span></span></span></span></a></span></em></span></span></span></span></span></span></span></span></span></span></span><span><span><span><span><span><em>(</em></span></span></span></span></span><span><span><span><span><span><em><a href="http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/HashOperations.html" rel="nofollow"><span><span><span><span><span><span><span style="color:#4a6782">H</span></span></span></span></span></span></span></a><span><span><span><span><span> key,</span></span></span></span></span></em></span></span></span></span></span> <span><span><span><span><span><em><a href="https://docs.oracle.com/javase/6/docs/api/java/lang/Object.html?is-external=true" rel="nofollow"><span><span><span><span><span><span><span style="color:#4a6782">Object</span></span></span></span></span></span></span></a><span><span><span><span><span>... hashKeys)</span></span></span></span></span></em></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></h2> <p><span><span><span><span><span><span style="color:#4d4d4d"><span><span><span><span><span><span><span><span><span><span><span><span><span style="background-color:#ffffff"><span><span>   <span><span><span><span><span><em>删除变量中的键值对,可以传入多个参数,删除多个键值对</em></span></span></span></span></span><span><span><span><span><span><em>。</em></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <ol><li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">redisTemplate.opsForHash().delete(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map1"</span></span></span></span></span></span></span>,<span><span><span><span><span><span style="color:#50a14f"><span>"map2"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">map = redisTemplate.opsForHash().entries(<span><span><span><span><span><span style="color:#50a14f"><span>"hashValue"</span></span></span></span></span></span></span>);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> </div> </li> <li> <div> <div>   </div> </div> <div> <div> <span><span><span><span><span><span><span><span><span><span><span><span><span><span><code class="language-java">System.out.println(<span><span><span><span><span><span style="color:#50a14f"><span>"通过delete(H key, Object... hashKeys)方法删除变量中的键值对后剩余的:"</span></span></span></span></span></span></span> + map);</code></span></span></span></span></span></span></span></span></span></span></span></span></span></span> </div> <div> <span id="OSC_h3_15"></span> <h3 style="text-align:start">(补充)注意:Map集合中put与putIfAbsent的区别</h3> <p style="color:#4d4d4d; text-align:start">put方法:</p> <pre style="text-align:start"> V put(K key, V value);</pre> <p style="color:#4d4d4d; text-align:start">putIfAbsent方法:</p> <pre style="text-align:start"> V putIfAbsent(K key, V value);</pre> <p style="color:#4d4d4d; text-align:start">这两种方法都是以key-value键值对的形式存在到map集合中,那么它们两个有什么区别呢?</p> <p style="color:#4d4d4d; text-align:start">我们可以从map官网注释中看出:</p> <p style="color:#4d4d4d; text-align:start">1.使用put方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,<span style="color:#f33b45">如果已经存在对应的值,则会覆盖旧值,value为新的值。</span></p> <p style="color:#4d4d4d; text-align:start">2.使用putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,<span style="color:#f33b45">如果已经存在对应的值,则依旧为原来的值。</span></p> </div> </div> </li> </ol><div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/botkenni/blog/4476781</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/delta" hreflang="zh-hans">Delta</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> </div> </div> Fri, 14 Aug 2020 04:06:47 +0000 被刻印的时光 ゝ 3755914 at https://www.e-learn.cn OpenUOM移动性改造-靠新的session iD而不是IP/Port识别客户端 https://www.e-learn.cn/topic/3710137 <span>OpenUOM移动性改造-靠新的session iD而不是IP/Port识别客户端</span> <span><span lang="" about="/user/70" typeof="schema:Person" property="schema:name" datatype="">蹲街弑〆低调</span></span> <span>2020-08-04 17:20:55</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p>写于2014/06/07</p> <p> </p> <span id="OSC_h2_1"></span> <h2>设备移动性的挑战</h2> <div> <p>1.设备会经常由于小区或模式切换而更改IP地址。</p> </div> <div> 这种地址更新是移动网络的正常行为,不应作为故障或事故看待,因此理应对应用程序透明,应用不应被此类事件打扰,更无责做善后处理。 </div> <div> <p>2.移动设备存在多张3G/4G/2.75G网卡时,希望这些网卡同时收发数据。</p> </div> <div> 由于这些网卡一般属于不同运营商网络,其网络架构又不同,一般要求数据包携带本运营商网卡的IP地址作为源(这一般是为了在该运营商核心网终点处做NAT),因此为了支持多运营商多网卡负载均衡,一个应用程序业务流数据包必然要支持不同的IP地址作为源,不幸的是,即便对于UDP而言,大多数应用也都是只支持单一源(它们会针对UDP socket调bind),以减少服务端的复杂性。 </div> <div> <p>3.经常性的失联</p> </div> <div> 电梯里,高铁上,山区景点盲区,公司的厕所...你会突然失联,然后突然出现!但是应用程序却不希望受到如此的折腾,对于OpenUOM而言,经过测试,一次重连大约要5秒时间,代价是高昂的,重新TLS握手,重新push,...实际上只要你的ping-restart时间足够小,对于信号缺失就会很迅速的被OpenUOM感知,解决方案就是将ping-restart放大,可是你也不知道自己失联多久。 <p>4.RRC相关造成的额外延时</p> 有时候,即便你处在信号很好的地方,也会发现打开一个网页非常慢,然后迅速就会变快,这其实是移动网络的本质,为了节省电量损耗,设备并不是一直和网络保持连接的,而是运行一种和Linux的NOHZ算法一样的机制,在设备长时间没有数据收发的时候,关闭连接,和Linux的NOHZ不同的是,NOHZ状态的脱离时间是明确的,它由下一个timer到期的时间以及时钟之外的任何中断的最小值决定,但是RRC机制却不同,数据什么时候会发送完全取决于神一样的用户,因此当有数据要发送的时候,必须重新接入移动网,协商参数等等,这无疑会消耗时间。这个抖动不是用户应用能解决的,因为这取决于设备厂商的实现以及移动网络的规范,这是一个纯粹的网络问题,因此本文不会涉及过多这方面的内容。 <span id="OSC_h2_2"></span> <h2>会话层真的太重要了</h2> </div> <div> 鉴于TCP/IP栈的抢先进化,其对手便永远失去了机会,因此应用程序一般都是直接接口在传输层协议之上,这是事实! </div> <div>        对于应用开发接口,应用程序的数据收发直接基于一个INET socket,而一个socket的“连接”通过五元组来标识,因此五元组的任何一个元素改变,或者说网络的任何一个事件都会影响到这个对应的socket,socket I/O接口的手册中明确给出了返回值和错误码,而直接调用这些接口的应用程序必须处理这种错误,因此网络事件便直接影响了应用程序! </div> <div>        但是网络事件不应影响应用,比如网络断了不一定让应用程序必须采取善后和重连,也许这只是暂时事件,比如IP地址变了。应用程序要做的就是生成业务数据并发送,它并不需要直接从socket接口获取并处理错误码。应用程序只需要知道发送数据发出了多少即可,即便真有严重事件需要彻底退出,也不该是来自TCP/IP的通知。那么一定需要一个新的层,历史缘故,我称它会话层吧。 <span id="OSC_h2_3"></span> <h2>OpenUOM的故事</h2> 我希望OpenUOM的处理层完全和网络状态脱离,即使客户端的IP地址变了,也能用新的IP地址继续和服务端通信,即使信号全无,一旦有了信号,通信继续进行,也就是说,网络状态不会打扰到OpenUOM进程的处理。为了一步步地满足这个需求,我们看一下OpenUOM目前的行为,两端连通以后,我试着改变客户端的IP地址,结果服务端报错: </div> <p> </p> <p>Wed Jan  1 00:58:46 2014 us=439027 GET INST BY VIRT: 0e:fe:bc:a3:6f:fe -&gt; zhaoya/192.168.1.197:33512 via 0e:fe:bc:a3:6f:fe<br /> Wed Jan  1 00:58:46 2014 us=439981 zhaoya/192.168.42.197:33512 UDPv4 WRITE [133] to 192.168.1.197:33512: P_DATA_V1 kid=0 DATA len=132<br /><span><strong>Wed Jan  1 00:58:46 2014 us=822941 TLS State Error: No TLS state for client 192.168.1.199:33512, opcode=6</strong></span><br /> Wed Jan  1 00:58:46 2014 us=823912 GET INST BY REAL: 192.168.1.199:33512 [failed]<br /> Wed Jan  1 00:58:47 2014 us=197871 MULTI: REAP range 128 -&gt; 144<br /> Wed Jan  1 00:58:47 2014 us=198861 TLS State Error: No TLS state for client 192.168.1.199:33512, opcode=6<br /> Wed Jan  1 00:58:47 2014 us=198887 GET INST BY REAL: 192.168.1.199:33512 [failed]<br /> ...上述原则上将陌生的IP/Port看成了新的TLS session,但是OpenUOM的TLS握手和网络根本就没有关系。它是在BIO上完成的TLS,用Reliable层保证了传输过程的可靠性。但是原谅这个报错吧,代码的初衷可能是防止Dos攻击而不是别的,因为如果没有经过成功的TLS握手,那么一个连接是不可能正常插进来的,否则TLS就该废掉了。现在着手自己的实现。思路是很清晰的,只是在OpenUOM的协议头里面增加一个字段:session ID,服务端用这个session ID识别和区别不同的客户端,不再基于客户端的IP/Port来识别和区别不同的客户端,这样的话,只要客户端发出的OpenUOM的数据包被服务端收到了,且解析出来的session ID可以对应到一个multi_instance,那么这个数据包就是合法的。<br />        因此,OpenUOM的数据收发和底层的网络状态彻底隔离了,只要用OpenUOM协议构造数据包即可,如果网络状况不好,那就发不出去,但是只要网络恢复,就可以发出去,只要发出去被服务端收到,就能识别和解析并对应到某个multi_instance,如果客户端IP地址变化了,只要保持到服务端IP地址的可达性,数据就能发送到服务端,只要能到服务端,服务端就能从OpenUOM协议包中解析出session ID,从而对应到一个multi_instance。<br />        思路有了,也很清晰,那么怎么改呢?<br /><br /><br /><br /><br /><br /><br /><br /><br /></p> <p> </p> <p> </p> <div> <span id="OSC_h2_4"></span> <h2>解决问题的步骤</h2> 写这篇文章并不是为了表达OpenUOM这个程序如何被用在移动设备上,这个可以写上一本书,本文的主要目的是想展示一种解决问题的方式,我在有了上面的思路后是如何验证其确实可行的呢?我并没有一头扎进那沸腾的代码,去实现最终的方案,比如直接就去修改OpenUOM的协议,而是先将代码写死,瞬间得到一个行或者不行的结论。这个过程要修改最少的代码!为了找到修改何处,还得从上面的报错入手。其在ssl.c的tls_pre_decrypt_lite函数报错,该函数没有任何关于multi_instance的信息,因此我知道在这个tls_pre_decrypt_lite函数调用之前,程序已经进入异常流了,因此就找tls_pre_decrypt_lite的调用代码,在mudp.c中的multi_get_create_instance_udp找到了: <br /><br />   <pre class="has"><code class="language-plain">struct multi_instance * multi_get_create_instance_udp (struct multi_context *m) { ... if (mroute_extract_openuom_sockaddr (&amp;real, &amp;m-&gt;top.c2.from.dest, true)) { struct hash_element *he; const uint32_t hv = hash_value (hash, &amp;real); struct hash_bucket *bucket = hash_bucket (hash, hv); hash_bucket_lock (bucket); he = hash_lookup_fast (hash, bucket, &amp;real, hv); if (he) { mi = (struct multi_instance *) he-&gt;value; } else { // 找不到multi_instance的异常流处理 if (!m-&gt;top.c2.tls_auth_standalone || tls_pre_decrypt_lite (m-&gt;top.c2.tls_auth_standalone, &amp;m-&gt;top.c2.from, &amp;m-&gt;top.c2.buf)) { // 异常流处理 } } ... }</code></pre> <br /> 关键是multi_instance没有找到,为什么呢?我发现mroute_extract_openuom_sockaddr的传入参数real,正是根据接收到的数据包的来源IP和端口初始化的,接下来查询multi_instance哈希表的时候,这个real就是key的值,在客户端的IP地址改变了之后,当然找不到任何value了,就算找到也是冲突链的value,最终返回的为NULL!接下来是关键点,既然是查询哈希表没有查到,并且是由于数据包的源IP/Port改变了没有找到,那么就忽略掉这个查询key,即想办法让这个查询百分百可以找到结果。这个思想是快速解决问题的关键,正是由于找不到key对应的value才失败,如果key能找到value的话要是能成功,问题就转化为了如何让key找到value而这我们已经有办法了,即从buffer里面取key,实际上这是另一个问题,这难道不是一次深刻的执果索因之旅吗?我在高中的物理竞赛中用此法获得了,唉,不提当年勇!这个思想很简单,但用的人不多,很多人都是一开始就修改OpenUOM协议,然后到最后一起调试,对于设计方案通过的研发任务,这是常规做法,但对于预研或极限开发来讲,这万万要不得!你根本就不知道自己的想法在OpenUOM既有框架内是否行得通,怎能一开始就大段改代码呢?R&amp;D没有写成RD是因为它们实际上不是一个部门,起码员工解决问题的思路是不同的,R部门侧重因果推导, <strong>执果索因</strong>,可行性验证,测试,D部门侧重设计,代码质量,进度控制,项目管理以及各种模型(迭代瀑布...)。 <br /><br /><br /></div> <p> </p> <div>        因此就重新定义hash_function以及hash_compare,让其返回定值!背后的思想是固定了hash key和hash compare结果之后,如果此时改变了客户端IP地址而依然不出错,就说明hash查找的过程已经和收到数据包的源IP地址和端口没有关系了,剩下的就是将这个hash key从固定值改为从收到的OpenUOM数据的协议头里面取就可以了。我的新版hash函数如下: <br />   <pre class="has"><code class="language-plain">m-&gt;hash = hash_init (t-&gt;options.real_hash_size, fake_addr_hash_function, fake_addr_compare_function); </code></pre> <br /> 其中: <br />   <pre class="has"><code class="language-plain">uint32_t fake_addr_hash_function(const void *key, uint32_t iv) { return 0x10101010; } bool fake_addr_compare_function(const void *key1, const void *key2) { return true; }</code></pre> <br /> 就改这些即可!服务端已经可以将客户端对应到唯一的那个multi_instance了,并且成功解析封装后的IP报文,可是发现服务端往客户端返回的时候没有通过,我通过192.168.1.199接入OpenUOM成功,然后将OpenUOM客户端的地址改为了192.168.1.197,OpenUOM客户端所在机器长ping服务端的虚拟IP地址,服务端日志打印如下: <br /><strong>Wed Jan  1 00:02:11 2014 us=389812 zhaoya/192.168.1.199:38310 UDPv4 WRITE [77] to 192.168.1.199:38310: P_DATA_V1 kid=0 DATA len=76</strong> <br /> 发现写入的目标地址还是192.168.1.199,为何没有切换到我新改的地址?我觉得这是一个小问题。我只要找到打印上面日志的位置就好,而这很简单,代码在forward.c的process_outgoing_link函数中,注意以下的代码: <br />   <pre class="has"><code class="language-plain">ASSERT (link_socket_actual_defined (c-&gt;c2.to_link_addr));</code></pre> 可见,这个to_link_addr是关键,这个值是OpenUOM客户端接入的时候生成的,以后不会变化,我只要将其改为实时更新的即可,就是说,无条件使用上次数据包的from地址,这些都在context_2结构体: <br />   <pre class="has"><code class="language-plain">struct context_2 { ... struct link_socket_actual *to_link_addr; /* IP address of remote */ struct link_socket_actual from; /* address of incoming datagram */ ... }</code></pre> <br /> 注释很清晰!怎么改呢?可以将使用to_link_addr的地方全部使用&amp;from,当然我不会这么做,因为这只是一个可行性证实,不是正儿八经的改代码,如此鲁莽是不对的,我的做法是添加一段临时代码: <br />   <pre class="has"><code class="language-plain">void process_outgoing_link (struct context *c) { struct gc_arena gc = gc_new (); perf_push (PERF_PROC_OUT_LINK); #if 1 // 吐嘈时骂过的,实际上我经常这么玩 { c-&gt;c2.to_link_addr = &amp;c-&gt;c2.from; } #endif ... }</code></pre> <br /> 至此,我认为当初的想法是可行的。事后,我试着在OpenUOM的协议中增加了一个32位的session ID,然后彻底更改了hash function,传入的key就是从BPTR(buf)中取出的这个session ID,并且我把OpenUOM客户端的数量增加到了3个,同样是一致的结果,时间定在了晚上1点35分。如果这是一个下雨的夜晚,我可能会做更多的修改,但是这是一个燥热的初夏之夜! <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div> <div>        修改OpenUOM以适应移动性这个想法是我突然想到的,由于近期工作基本和网络无关,且比较杂乱又有严格deadline,我也就不能在工作时间有那么多的闲情雅致,只能选一个下雨的夜晚来折腾。可是雨到底也没来,我也就只能做个半拉子,还有哪些方面没做呢?难道上面说的不就是全部吗?不是全部,很多细节都没有处理,比如客户端改变IP地址后服务端要即使更新该客户端对应的multi_instance中相关数据结构,比如echo机制的ping替换各发各自的ping机制,另外各种restart重连机制也要被替换,移动环境中,很多在非移动环境中发生的导致应用必须重连重置的网络事件都是正常的,因此必须最少化重连重置操作,需要做的就两件事,一是继续发送,二是等! </div> <div> <span id="OSC_h2_5"></span> <h2>关于本文的引申</h2> 不能杜绝问题的发生,那就忽略掉问题,使其对自身毫无影响。多加一个层就可以隔离问题!你不能让天公不下雨,但你能带上伞或穿上雨衣雨鞋,或者将活动改在室内,再或者像我这样,尽情雨中欢呼...如果你为了不下雨而去研究大气运行原理,研究让云层散开的炮弹,那你就走偏了,虽然最终你可能会成为伟大科学家,但目前,你可能只是因为下雨影响了你的心情,而已。 <br />        在定位问题的过程中,千万不要过早扎入代码细节,用最快的方式验证可行性和合理性。然后再细嚼慢咽,要分清主要问题和次要问题,主要问题简化其本质,次要问题模拟其现象,不应该为次要问题浪费大量时间和精力。你不可能一次搞定所有问题,学会模拟当前非本质问题造成的现象是一种技巧技能,能从简化环境中得到真实结论是一种推理技能。 <br /></div> <div>        我举一个我早年的反例子。有一次因为文件写入出错,搞了我一个多礼拜没搞定,最终也没搞定,但是却学会了ext2文件系统的数据恢复,八杆子打不着的一个问题,而且不是用debugfs实现,是自己编程哦!对个人好奇心而言,我没什么损失,可是却耽误了进度,其实最可悲的是那些不是好奇心使然的coder,迷迷糊糊就到了内核驱动,然后一无所获或者鼻青脸肿出来... </div> <div>        要问我为何喜欢雨天,也许它能将飘忽在天<div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/4376383/blog/4332126</code></p></div></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/linux" hreflang="zh-hans">Linux</a></div> <div class="field--item"><a href="/tag/bind" hreflang="zh-hans">bind</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/inet" hreflang="zh-hans">iNet</a></div> </div> </div> Tue, 04 Aug 2020 09:20:55 +0000 蹲街弑〆低调 3710137 at https://www.e-learn.cn redis 大key 问题 https://www.e-learn.cn/topic/3704134 <span>redis 大key 问题</span> <span><span lang="" about="/user/58" typeof="schema:Person" property="schema:name" datatype="">空扰寡人</span></span> <span>2020-07-29 00:51:26</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p>命令:redis-cli *******  --bigkeys</p> <p><img height="1051" width="1000" class="b-lazy" data-src="https://oscimg.oschina.net/oscnet/up-ea80022c27106f2247c2cc95e92a4775bd4.png" data-original="https://oscimg.oschina.net/oscnet/up-ea80022c27106f2247c2cc95e92a4775bd4.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /></p> <div> <div> redis-cli --bigkeys的优点是可以在线扫描,不阻塞服务;缺点是信息较少,内容不够精确。扫描结果中只有string类型是以字节长度为衡量标准的。List、set、zset等都是以元素个数作为衡量标准,元素个数多不能说明占用内存就一定多 </div> <span id="OSC_h1_1"></span> <h1><br /><strong>处理方法:</strong></h1> <p style="color:#333333; text-align:left">由于redis是单线程运行的,如果一次操作的value很大会对整个redis的响应时间造成负面影响,所以业务上通常会以以下方式进行分拆。</p> <span id="OSC_h2_2"></span> <h2>分拆</h2> <span id="OSC_h3_3"></span> <h3>单个key存储大value</h3> <p style="color:#333333; text-align:left"><strong>每次都是整存整取</strong></p> <p style="color:#333333; text-align:left">这种操作一般都是每次整存整取,这种情况可以尝试将对象拆分成多个key-value,使用multiGet获取值,这样分拆意义在于分拆操作的压力,将操作压力平摊到多个redis实例,降低对于单个redis的io压力。</p> <p style="color:#333333; text-align:left"><strong>每次只存取部分数据</strong></p> <p style="color:#333333; text-align:left">同样可以拆成几个key-value,也可以将这些存储在一个hash中,每个field代表具体属性,使用hget,hmget来获取部分value,使用hset,hmset来更新部分属性。</p> <span id="OSC_h3_4"></span> <h3>hash,set,zset,list中存储过多数据</h3> <p style="color:#333333; text-align:left">同样可以将这部分元素拆分,以hash为例,正常的流程是:hget(hashKey, field);hset(hashKey, field, value)。 现在可以固定一个桶数量,比如1w,每次存取的时候,先在本地计算field的hash值,对1w取模,确定field落在哪个key上。</p> <blockquote> <p>newHashKey = hashKey + ( hash(field) % 10000); hset (newHashKey, field, value) ; hget(newHashKey, field)</p> </blockquote> <p style="color:#333333; text-align:left">set,zset,list做法类似。</p> <span id="OSC_h3_5"></span> <h3>一个集群存储了上亿的key</h3> <p style="color:#333333; text-align:left">如果key个数过多会带来更多的内存占用空间:</p> <ol><li>key本身占用。</li> <li>集群中,服务端会建立slot2key的映射关系,这种指针占用在key多的情况下存在巨大的空间浪费,在key上亿时,内存消耗十分明显。</li> </ol><p style="color:#333333; text-align:left">减少key个数可以减少对内存的消耗,可以参考hash结构存储,将多个key存储在一个hash结构中。</p> <p style="color:#333333; text-align:left">组合那些key本身强相关性的,比如key代表一个对象,m每个key是对象的一个属性,按照这种方式设置一个新的key-hash的结构,原先的key作为这个新hash field。</p> <p style="color:#333333; text-align:left">比如:</p> <blockquote> <p>将user.zhangsan.id= 123,user.zhangsan.age = 18,user.zhangsan.country = china 改成 key = user.zhangsan field:id = 123 field:age = 18 field:country = china</p> </blockquote> <p style="color:#333333; text-align:left">如果key本身没有相关性,可以预估总量,对一些场景预分固定的桶数量。</p> <p style="color:#333333; text-align:left">比如有2亿key,按照一个hash存储100个field来算,需要200w个桶,这样可以按照200w个固定桶数量做取模,hash(123456) % 200w,比如算出3个key的桶分别是1,2,3。调用存储api hset(key, field, value),读取时用hget(key,field)。 建议分桶数量100合适。</p> <span id="OSC_h3_6"></span> <h3>Bitmap和Bloom拆分</h3> <p style="color:#333333; text-align:left">使用Bloom的场景往往是数据量极大的情况,这种情况下,bitmap和bloom使用空间比较大。</p> <p style="color:#333333; text-align:left">如果bitmap比较大,可以拆分成多个小的bitmap,可以通过结合hash方式,将key路由到hash上对应的bitmap上,将不同的key分配给不同的bitmap,而不是所有小的bitmap当作一个整体,这样每次请求都只要取redis中的一个key即可。</p> </div> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/shunshun/blog/4411426</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/redis-cli" hreflang="zh-hans">redis-cli</a></div> <div class="field--item"><a href="/tag/redis" hreflang="zh-hans">Redis</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> </div> </div> Tue, 28 Jul 2020 16:51:26 +0000 空扰寡人 3704134 at https://www.e-learn.cn search(6)- elastic4s-CRUD https://www.e-learn.cn/topic/3588565 <span>search(6)- elastic4s-CRUD</span> <span><span lang="" about="/user/115" typeof="schema:Person" property="schema:name" datatype="">♀尐吖头ヾ</span></span> <span>2020-04-23 07:18:02</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p><span style="font-family: 宋体; font-size: 14px;">    如果我们把ES作为某种数据库来使用的话,必须熟练掌握ES的CRUD操作。在这之前先更正一下上篇中关于检查索引是否存在的方法:elastic4s的具体调用如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> <span style="color: #008000;">//</span><span style="color: #008000;">删除索引</span> val rspExists = client.execute(indexExists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (rspExists.result.exists) client.execute(deleteIndex(</span><span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span></span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">在下面我们还会示范如何检查一条记录(document)是否存在的方法。</span></p> <p><span style="font-family: 宋体; font-size: 14px;">先示范新建一条记录。一般来讲数据库表都有个唯一字段,最好用ES里的id来代表,否则ES会自动产生一个唯一id,那么随机读取get时就会很不方便。如果新插入的记录id已经在表里存在,ES会替换新的内容,不会产生异常。可以在elastic4s里使用createOnly(true)来强制产生重复id异常:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;">import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties} import com.sksamuel.elastic4s.akka._ import akka.actor._ import scala.concurrent.ExecutionContext.Implicits.</span><span style="color: #0000ff;">global</span> <span style="color: #0000ff;">object</span><span style="color: #000000;"> Lesson05 extends App { import com.sksamuel.elastic4s.ElasticDsl._ </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">implicit</span> lazy val system: ActorSystem =<span style="color: #000000;"> ActorSystem() val akkaClient </span>= AkkaHttpClient(AkkaHttpClientSettings(List(<span style="color: #800000;">"</span><span style="color: #800000;">130.1.1.234:9200</span><span style="color: #800000;">"</span><span style="color: #000000;">))) val client </span>=<span style="color: #000000;"> ElasticClient(akkaClient) val publisher </span>= indexInto(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>).id(<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">) .fields( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">人民出版社</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">biztype</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">出版社</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">addr</span><span style="color: #800000;">"</span> -&gt;<span style="color: #000000;"> Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">district</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">北京市东城区</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">address</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">朝阳门内大街166号</span><span style="color: #800000;">"</span><span style="color: #000000;"> ), </span><span style="color: #800000;">"</span><span style="color: #800000;">regdate</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">1963-02-18</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">contact</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">65122634@163.com</span><span style="color: #800000;">"</span><span style="color: #000000;"> ).createOnly(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">) val pubExists </span>= client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (pubExists.isSuccess) { val createPub </span>= client.execute(publisher).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (createPub.isSuccess) { val pub </span>= client.execute(<span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>).fetchSourceContext(<span style="color: #0000ff;">true</span>)).<span style="color: #0000ff;">await</span><span style="color: #000000;"> println(s</span><span style="color: #800000;">"</span><span style="color: #800000;">${pub.result.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${createPub.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${pubExists.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) val dstributor </span>= indexInto(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>).id(<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) .fields( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">新华文轩出版传媒股份有限公司</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">biztype</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">出版发行</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">addr</span><span style="color: #800000;">"</span> -&gt;<span style="color: #000000;"> Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">district</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">四川省成都市锦江区</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">address</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">金石路239号4栋1层1号</span><span style="color: #800000;">"</span><span style="color: #000000;"> ), </span><span style="color: #800000;">"</span><span style="color: #800000;">regdate</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">2005-03-09</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">contact</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">52635286@qq.com</span><span style="color: #800000;">"</span><span style="color: #000000;"> ).createOnly(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">) val grpExists </span>= client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (grpExists.isSuccess) { val createGroup </span>= client.execute(dstributor).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (createGroup.isSuccess) { val dstr </span>= client.execute(<span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span>).fetchSourceContext(<span style="color: #0000ff;">true</span>)).<span style="color: #0000ff;">await</span><span style="color: #000000;"> println(s</span><span style="color: #800000;">"</span><span style="color: #800000;">${dstr.result.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${createGroup.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${grpExists.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) val mget </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) )).</span><span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;">(mget.isSuccess) mget.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt; println(s<span style="color: #800000;">"</span><span style="color: #800000;">${i.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">)) </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${mget.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) scala.io.StdIn.readLine() system.terminate() client.close() }</span></span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">上面示范了不同类型字段的填写方式,特别是nested字段如addr。每插入一条新记录就用get进行一次验证,输出显示:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;">HashMap(name -&gt; 人民出版社, regdate -&gt; <span style="color: #800080;">1963</span>-<span style="color: #800080;">02</span>-<span style="color: #800080;">18</span>, contact -&gt; <span style="color: #800080;">65122634</span>@<span style="color: #800080;">163</span>.com, code -&gt; c00001, addr -&gt; Map(district -&gt; 北京市东城区, address -&gt; 朝阳门内大街166号), biztype -&gt;<span style="color: #000000;"> 出版社) HashMap(name </span>-&gt; 新华文轩出版传媒股份有限公司, regdate -&gt; <span style="color: #800080;">2005</span>-<span style="color: #800080;">03</span>-<span style="color: #800080;">09</span>, contact -&gt; <span style="color: #800080;">52635286</span>@qq.com, code -&gt; c00002, addr -&gt; Map(district -&gt; 四川省成都市锦江区, address -&gt; 金石路239号4栋1层1号), biztype -&gt;<span style="color: #000000;"> 出版发行) HashMap(name </span>-&gt; 人民出版社, regdate -&gt; <span style="color: #800080;">1963</span>-<span style="color: #800080;">02</span>-<span style="color: #800080;">18</span>, contact -&gt; <span style="color: #800080;">65122634</span>@<span style="color: #800080;">163</span>.com, code -&gt; c00001, addr -&gt; Map(district -&gt; 北京市东城区, address -&gt; 朝阳门内大街166号), biztype -&gt;<span style="color: #000000;"> 出版社) HashMap(name </span>-&gt; 新华文轩出版传媒股份有限公司, regdate -&gt; <span style="color: #800080;">2005</span>-<span style="color: #800080;">03</span>-<span style="color: #800080;">09</span>, contact -&gt; <span style="color: #800080;">52635286</span>@qq.com, code -&gt; c00002, addr -&gt; Map(district -&gt; 四川省成都市锦江区, address -&gt; 金石路239号4栋1层1号), biztype -&gt; 出版发行)</span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">上面提到过,如果我们想把ES当作普通的数据库来使用的话,还是要备齐了CRUD功能。具体操作按照关系数据库方式围绕着唯一键id进行。比如,我们可以用id来检查记录是否已经存在:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> val pubExists = client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span> (pubExists.isSuccess) {...}</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">上面我们示范了针对索引的create,read操作。下面讨论一下update:update 可分单笔或批次两类,分别为:updateById, updateByQuery,很明显:updateByQuery是以query作为目标筛选条件的成批update操作。与上面的create操作一样,我们还是需要考虑唯一键id,这个可以在updateById操作里处理:当目标id存在时,用update请求里的字段值更新对应的字段。如目标id不存在的话就把update请求里的字段值当作新记录内容插入:</span></p> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">import com.sksamuel.elastic4s.http.JavaClient import com.sksamuel.elastic4s.requests.common.RefreshPolicy import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties} import scala.concurrent.ExecutionContext.Implicits.</span><span style="color: #0000ff;">global</span> <span style="color: #0000ff;">object</span><span style="color: #000000;"> Lesson06 extends App { import com.sksamuel.elastic4s.ElasticDsl._ val esjava </span>= JavaClient(ElasticProperties(<span style="color: #800000;">"</span><span style="color: #800000;">http://localhost:9200</span><span style="color: #800000;">"</span><span style="color: #000000;">)) val client </span>=<span style="color: #000000;"> ElasticClient(esjava) val doc1 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company1</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val doc2 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company2</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val doc3 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company3</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val updateAll </span>= <span style="color: #0000ff;">for</span><span style="color: #000000;"> { _ </span>&lt;-<span style="color: #000000;"> client.execute(doc1) _ </span>&lt;-<span style="color: #000000;"> client.execute(doc2) _ </span>&lt;-<span style="color: #000000;"> client.execute(doc3) } </span><span style="color: #0000ff;">yield</span><span style="color: #000000;">() updateAll.</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> val getResults </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">) ) ).</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> getResults.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt;<span style="color: #000000;"> println(i.sourceAsMap)) client.close() }</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">成批更新比较麻烦,因为通常每条记录的更新都可能涉及到当前记录的字段值,或作为判断条件,或为更新值,我们需要使用并处理当前记录中某些字段。这就需要在数据层面运行某些计算方法,可以用脚本语言来实现这样的功能,如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;"> import com.sksamuel.elastic4s.requests.script.Script val script </span>= <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.fullname = ctx._source.code+' '+ctx._source.name</span><span style="color: #800000;">"</span><span style="color: #000000;"> val updateByQ </span>= updateIn(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">) .query(matchQuery(</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">)) .script(Script(script,Some(</span><span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;">))) val qupResult </span>= client.execute(updateByQ).<span style="color: #0000ff;">await</span><span style="color: #000000;"> val getResults </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">) ) ).</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> getResults.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt; println(i.sourceAsMap))</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">与update一样,delete也分单个或成批删除模式。delete by Id 示例如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> (<span style="color: #0000ff;">for</span><span style="color: #000000;"> { _ </span>&lt;- client.execute(delete(<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span>).<span style="color: #0000ff;">from</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">)) _ </span>&lt;- client.execute(deleteByQuery(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">)) } </span><span style="color: #0000ff;">yield</span>()).<span style="color: #0000ff;">await</span></span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">delete by Query 用法如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;"> import com.sksamuel.elastic4s.Index._ client.execute( deleteByQuery(toIndex(</span><span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">), termQuery(</span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">)) ).</span><span style="color: #0000ff;">await</span></span></code></pre> </div> <p> </p> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/4409432/blog/3300552</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/scala" hreflang="zh-hans">scala</a></div> <div class="field--item"><a href="/tag/elastic" hreflang="zh-hans">Elastic</a></div> <div class="field--item"><a href="/tag/akka" hreflang="zh-hans">akka</a></div> <div class="field--item"><a href="/tag/readline" hreflang="zh-hans">readline</a></div> </div> </div> Wed, 22 Apr 2020 23:18:02 +0000 ♀尐吖头ヾ 3588565 at https://www.e-learn.cn search(6)- elastic4s-CRUD https://www.e-learn.cn/topic/3588423 <span>search(6)- elastic4s-CRUD</span> <span><span lang="" about="/user/136" typeof="schema:Person" property="schema:name" datatype="">扶醉桌前</span></span> <span>2020-04-23 05:05:08</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p><span style="font-family: 宋体; font-size: 14px;">    如果我们把ES作为某种数据库来使用的话,必须熟练掌握ES的CRUD操作。在这之前先更正一下上篇中关于检查索引是否存在的方法:elastic4s的具体调用如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> <span style="color: #008000;">//</span><span style="color: #008000;">删除索引</span> val rspExists = client.execute(indexExists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (rspExists.result.exists) client.execute(deleteIndex(</span><span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span></span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">在下面我们还会示范如何检查一条记录(document)是否存在的方法。</span></p> <p><span style="font-family: 宋体; font-size: 14px;">先示范新建一条记录。一般来讲数据库表都有个唯一字段,最好用ES里的id来代表,否则ES会自动产生一个唯一id,那么随机读取get时就会很不方便。如果新插入的记录id已经在表里存在,ES会替换新的内容,不会产生异常。可以在elastic4s里使用createOnly(true)来强制产生重复id异常:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;">import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties} import com.sksamuel.elastic4s.akka._ import akka.actor._ import scala.concurrent.ExecutionContext.Implicits.</span><span style="color: #0000ff;">global</span> <span style="color: #0000ff;">object</span><span style="color: #000000;"> Lesson05 extends App { import com.sksamuel.elastic4s.ElasticDsl._ </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">implicit</span> lazy val system: ActorSystem =<span style="color: #000000;"> ActorSystem() val akkaClient </span>= AkkaHttpClient(AkkaHttpClientSettings(List(<span style="color: #800000;">"</span><span style="color: #800000;">130.1.1.234:9200</span><span style="color: #800000;">"</span><span style="color: #000000;">))) val client </span>=<span style="color: #000000;"> ElasticClient(akkaClient) val publisher </span>= indexInto(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>).id(<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">) .fields( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">人民出版社</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">biztype</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">出版社</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">addr</span><span style="color: #800000;">"</span> -&gt;<span style="color: #000000;"> Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">district</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">北京市东城区</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">address</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">朝阳门内大街166号</span><span style="color: #800000;">"</span><span style="color: #000000;"> ), </span><span style="color: #800000;">"</span><span style="color: #800000;">regdate</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">1963-02-18</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">contact</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">65122634@163.com</span><span style="color: #800000;">"</span><span style="color: #000000;"> ).createOnly(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">) val pubExists </span>= client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (pubExists.isSuccess) { val createPub </span>= client.execute(publisher).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (createPub.isSuccess) { val pub </span>= client.execute(<span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>).fetchSourceContext(<span style="color: #0000ff;">true</span>)).<span style="color: #0000ff;">await</span><span style="color: #000000;"> println(s</span><span style="color: #800000;">"</span><span style="color: #800000;">${pub.result.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${createPub.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${pubExists.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) val dstributor </span>= indexInto(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>).id(<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) .fields( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">新华文轩出版传媒股份有限公司</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">biztype</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">出版发行</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">addr</span><span style="color: #800000;">"</span> -&gt;<span style="color: #000000;"> Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">district</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">四川省成都市锦江区</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">address</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">金石路239号4栋1层1号</span><span style="color: #800000;">"</span><span style="color: #000000;"> ), </span><span style="color: #800000;">"</span><span style="color: #800000;">regdate</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">2005-03-09</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">contact</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">52635286@qq.com</span><span style="color: #800000;">"</span><span style="color: #000000;"> ).createOnly(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">) val grpExists </span>= client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (grpExists.isSuccess) { val createGroup </span>= client.execute(dstributor).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (createGroup.isSuccess) { val dstr </span>= client.execute(<span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span>).fetchSourceContext(<span style="color: #0000ff;">true</span>)).<span style="color: #0000ff;">await</span><span style="color: #000000;"> println(s</span><span style="color: #800000;">"</span><span style="color: #800000;">${dstr.result.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${createGroup.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) } </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${grpExists.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) val mget </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) )).</span><span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span><span style="color: #000000;">(mget.isSuccess) mget.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt; println(s<span style="color: #800000;">"</span><span style="color: #800000;">${i.sourceAsMap}</span><span style="color: #800000;">"</span><span style="color: #000000;">)) </span><span style="color: #0000ff;">else</span> println(s<span style="color: #800000;">"</span><span style="color: #800000;">${mget.error.reason}</span><span style="color: #800000;">"</span><span style="color: #000000;">) scala.io.StdIn.readLine() system.terminate() client.close() }</span></span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">上面示范了不同类型字段的填写方式,特别是nested字段如addr。每插入一条新记录就用get进行一次验证,输出显示:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;">HashMap(name -&gt; 人民出版社, regdate -&gt; <span style="color: #800080;">1963</span>-<span style="color: #800080;">02</span>-<span style="color: #800080;">18</span>, contact -&gt; <span style="color: #800080;">65122634</span>@<span style="color: #800080;">163</span>.com, code -&gt; c00001, addr -&gt; Map(district -&gt; 北京市东城区, address -&gt; 朝阳门内大街166号), biztype -&gt;<span style="color: #000000;"> 出版社) HashMap(name </span>-&gt; 新华文轩出版传媒股份有限公司, regdate -&gt; <span style="color: #800080;">2005</span>-<span style="color: #800080;">03</span>-<span style="color: #800080;">09</span>, contact -&gt; <span style="color: #800080;">52635286</span>@qq.com, code -&gt; c00002, addr -&gt; Map(district -&gt; 四川省成都市锦江区, address -&gt; 金石路239号4栋1层1号), biztype -&gt;<span style="color: #000000;"> 出版发行) HashMap(name </span>-&gt; 人民出版社, regdate -&gt; <span style="color: #800080;">1963</span>-<span style="color: #800080;">02</span>-<span style="color: #800080;">18</span>, contact -&gt; <span style="color: #800080;">65122634</span>@<span style="color: #800080;">163</span>.com, code -&gt; c00001, addr -&gt; Map(district -&gt; 北京市东城区, address -&gt; 朝阳门内大街166号), biztype -&gt;<span style="color: #000000;"> 出版社) HashMap(name </span>-&gt; 新华文轩出版传媒股份有限公司, regdate -&gt; <span style="color: #800080;">2005</span>-<span style="color: #800080;">03</span>-<span style="color: #800080;">09</span>, contact -&gt; <span style="color: #800080;">52635286</span>@qq.com, code -&gt; c00002, addr -&gt; Map(district -&gt; 四川省成都市锦江区, address -&gt; 金石路239号4栋1层1号), biztype -&gt; 出版发行)</span></code></pre> </div> <p><span style="font-family: 宋体; font-size: 14px;">上面提到过,如果我们想把ES当作普通的数据库来使用的话,还是要备齐了CRUD功能。具体操作按照关系数据库方式围绕着唯一键id进行。比如,我们可以用id来检查记录是否已经存在:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> val pubExists = client.execute(exists(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c00001</span><span style="color: #800000;">"</span>)).<span style="color: #0000ff;">await</span> <span style="color: #0000ff;">if</span> (pubExists.isSuccess) {...}</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">上面我们示范了针对索引的create,read操作。下面讨论一下update:update 可分单笔或批次两类,分别为:updateById, updateByQuery,很明显:updateByQuery是以query作为目标筛选条件的成批update操作。与上面的create操作一样,我们还是需要考虑唯一键id,这个可以在updateById操作里处理:当目标id存在时,用update请求里的字段值更新对应的字段。如目标id不存在的话就把update请求里的字段值当作新记录内容插入:</span></p> <div class="cnblogs_code"> <pre><code><span style="color: #000000;">import com.sksamuel.elastic4s.http.JavaClient import com.sksamuel.elastic4s.requests.common.RefreshPolicy import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties} import scala.concurrent.ExecutionContext.Implicits.</span><span style="color: #0000ff;">global</span> <span style="color: #0000ff;">object</span><span style="color: #000000;"> Lesson06 extends App { import com.sksamuel.elastic4s.ElasticDsl._ val esjava </span>= JavaClient(ElasticProperties(<span style="color: #800000;">"</span><span style="color: #800000;">http://localhost:9200</span><span style="color: #800000;">"</span><span style="color: #000000;">)) val client </span>=<span style="color: #000000;"> ElasticClient(esjava) val doc1 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company1</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val doc2 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company2</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val doc3 </span>= updateById(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">) .docAsUpsert( Map( </span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">, </span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span> -&gt; <span style="color: #800000;">"</span><span style="color: #800000;">test company3</span><span style="color: #800000;">"</span><span style="color: #000000;"> ) ) val updateAll </span>= <span style="color: #0000ff;">for</span><span style="color: #000000;"> { _ </span>&lt;-<span style="color: #000000;"> client.execute(doc1) _ </span>&lt;-<span style="color: #000000;"> client.execute(doc2) _ </span>&lt;-<span style="color: #000000;"> client.execute(doc3) } </span><span style="color: #0000ff;">yield</span><span style="color: #000000;">() updateAll.</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> val getResults </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span>).fetchSourceInclude(<span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span><span style="color: #000000;">) ) ).</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> getResults.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt;<span style="color: #000000;"> println(i.sourceAsMap)) client.close() }</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">成批更新比较麻烦,因为通常每条记录的更新都可能涉及到当前记录的字段值,或作为判断条件,或为更新值,我们需要使用并处理当前记录中某些字段。这就需要在数据层面运行某些计算方法,可以用脚本语言来实现这样的功能,如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;"> import com.sksamuel.elastic4s.requests.script.Script val script </span>= <span style="color: #800000;">"</span><span style="color: #800000;">ctx._source.fullname = ctx._source.code+' '+ctx._source.name</span><span style="color: #800000;">"</span><span style="color: #000000;"> val updateByQ </span>= updateIn(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">) .query(matchQuery(</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">)) .script(Script(script,Some(</span><span style="color: #800000;">"</span><span style="color: #800000;">painless</span><span style="color: #800000;">"</span><span style="color: #000000;">))) val qupResult </span>= client.execute(updateByQ).<span style="color: #0000ff;">await</span><span style="color: #000000;"> val getResults </span>=<span style="color: #000000;"> client.execute(multiget( </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">), </span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">) ) ).</span><span style="color: #0000ff;">await</span><span style="color: #000000;"> getResults.result.items.</span><span style="color: #0000ff;">foreach</span>(i =&gt; println(i.sourceAsMap))</span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">与update一样,delete也分单个或成批删除模式。delete by Id 示例如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"> (<span style="color: #0000ff;">for</span><span style="color: #000000;"> { _ </span>&lt;- client.execute(delete(<span style="color: #800000;">"</span><span style="color: #800000;">t00001</span><span style="color: #800000;">"</span>).<span style="color: #0000ff;">from</span>(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">)) _ </span>&lt;- client.execute(deleteByQuery(<span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">t00002</span><span style="color: #800000;">"</span><span style="color: #000000;">)) } </span><span style="color: #0000ff;">yield</span>()).<span style="color: #0000ff;">await</span></span></code></pre> </div> <p><span style="font-size: 14px; font-family: 宋体;">delete by Query 用法如下:</span></p> <div class="cnblogs_code"> <pre><code><span style="font-size: 14px;"><span style="color: #000000;"> import com.sksamuel.elastic4s.Index._ client.execute( deleteByQuery(toIndex(</span><span style="color: #800000;">"</span><span style="color: #800000;">company</span><span style="color: #800000;">"</span><span style="color: #000000;">), termQuery(</span><span style="color: #800000;">"</span><span style="color: #800000;">code</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">t00003</span><span style="color: #800000;">"</span><span style="color: #000000;">)) ).</span><span style="color: #0000ff;">await</span></span></code></pre> </div> <p> </p> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/4312361/blog/3301102</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/scala" hreflang="zh-hans">scala</a></div> <div class="field--item"><a href="/tag/elastic" hreflang="zh-hans">Elastic</a></div> <div class="field--item"><a href="/tag/akka" hreflang="zh-hans">akka</a></div> <div class="field--item"><a href="/tag/readline" hreflang="zh-hans">readline</a></div> </div> </div> Wed, 22 Apr 2020 21:05:08 +0000 扶醉桌前 3588423 at https://www.e-learn.cn [转帖]RocksDB简介 https://www.e-learn.cn/topic/3579845 <span>[转帖]RocksDB简介</span> <span><span lang="" about="/user/81" typeof="schema:Person" property="schema:name" datatype="">人盡茶涼</span></span> <span>2020-04-17 08:25:31</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p class="ad-wrap"> <a data-traceid="blog_detail_above_text_link_1" data-tracepid="blog_detail_above_text_link" style="color:#A00; font-weight:bold;" href="https://www.oschina.net/action/visit/ad?id=1147" target="_blank" rel="nofollow">【推荐阅读】微服务还能火多久?&gt;&gt;&gt; <img align="absmiddle" style="max-height: 32px;max-width: 32px;margin-top: -4px;" class="b-lazy" data-src="https://www.oschina.net/img/hot3.png" data-original="https://www.oschina.net/img/hot3.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /></a> </p> <span id="OSC_h1_1"></span> <h1>RocksDB简介</h1> <div class="rEsl9f"> <div class="_2mYfmT"> <div class="cnblogs_code"> <pre><code>https:<span style="color: #008000;">//</span><span style="color: #008000;">www.jianshu.com/p/a0088d7e9b97</span></code></pre> </div> <p> </p> </div> </div> <span id="OSC_h3_2"></span> <h3>1、RocksDB简介</h3> <p>RocksDB项目起源于Facebook的一个实验项目,该项目旨在开发一个与快速存储器(尤其是闪存)存储数据性能相当的数据库软件,以应对高负载服务。<br />这是一个c++库,可用于存储键和值,可以是任意大小的字节流。它支持原子读和写。<br />RocksDB具有高度灵活的配置功能,可以通过配置使其运行在各种各样的生产环境,包括纯内存,Flash,硬盘或HDFS。它支持各种压缩算法,并提供了便捷的生产环境维护和调试工具。<br /><br /></p> <span id="OSC_h3_3"></span> <h3>2、假设和目标</h3> <span id="OSC_h4_4"></span> <h4>性能:</h4> <p>RocksDB的主要设计目标是保证存取快速存储器和高负载服务器更高效,保证充分利用Flash或RAM子系统提供的高速率读写,支持高效的查找和范围scan,支持高负载的随机读、高负载的更新操作或两者的结合。其架构应该支持高并发读写和容量大增时系统的一致性。</p> <span id="OSC_h4_5"></span> <h4>向后兼容性:</h4> <p>这个软件的新版本应该是向后兼容的,因此,当升级到新版本时现有的应用程序不需要改变。</p> <span id="OSC_h3_6"></span> <h3>3、高级体系结构</h3> <p>RocksDB是一个嵌入式键值存储器,其中键和值是任意的字节流。RocksDB中的所有数据是按序存放的。常见操作包括Get(key), Put(key), Delete(key) and Scan(key)。<br />RocksDB有三个基本结构:RocksDB memtable,sstfile和logfile。memtable是一个内存数据结构——新数据会插入到memtable和日志文件(可选)。日志文件是顺序写入的,位于磁盘。当memtable写满后,数据会被刷新到磁盘上的sstfile文件,同时相应的日志文件可以安全地删除。sstfile中的数据经过排序的,目的是为了加快键查找。<br /></p> <span id="OSC_h3_7"></span> <h3>4、特性</h3> <span id="OSC_h4_8"></span> <h4>Gets,迭代器和快照</h4> <p>键和值被视为纯字节流,没有大小的限制。<br />Get接口允许应用程序从数据库中获取一个键值。MultiGet接口允许应用程序从数据库中检索多个键值。MultiGet接口返回的key-value对都是相互匹配的。所有数据库中的数据都按顺序存放。应用程序可以指定一个key比较方法来定义key的排序顺序。迭代器允许应用程序对数据库进行RangeScan。<br />迭代器可以先定位一个指定的键,然后应用程序就可以从这个定位点开始一个一个扫描key。迭代器还可以用来对key做反向迭代。创建迭代器是会创建当前数据库的一个快照视图,因此,通过迭代器返回的所有键都来自同一个数据库视图。<br />Snapshot允许应用程序创建一个快照视图。Get和迭代器可以从一个指定的快照读取数据。在某种意义上,Snapshot和迭代器都提供了某个时间点上数据库的快照视图,但两者的实现是不同的。<br />短暂的扫描最好通过迭代器而耗时较长的扫描最好通过快照。迭代器记录了数据库当前视图对应文件,直到迭代器被释放才删除这些。而快照并不能阻止文件删除;相反,compaction流程知道当前的快照并且不会删除任何现有快照中的key。数据库重启后,快照将丢失。重载RocksDB(通过服务器重启)会释放所有先前的快照。<br /><br /><br /><br /></p> <span id="OSC_h4_9"></span> <h4>前缀迭代器</h4> <p>大多数LSM引擎无法支持一个高效RangeScan,因为它需要查找每一个数据文件。但大多数应用程序不会对key进行随机扫描,而更多的是扫描给定前缀的key。<br />RocksDB利用了这种优势。应用程序可以通过prefix_extractor指定一个key的前缀。RocksDB用此来保存每个key前缀的bloom,指定了前缀(通过ReadOptions)<br />的迭代器将使用bloom二进制位来避免查找不包含指定key前缀的文件。<br /><br /></p> <span id="OSC_h4_10"></span> <h4>更新</h4> <p>Put操作向数据库插入单个key-value。如果键已经存在,旧值将被覆盖。Writer操作允许将多个keys-values原子地插入到数据库中。数据库保证同一个Writer操作<br />中的所有keys-values要么全部插入,要么都不插入。如果其中任何一个键已经存在于数据库中,旧值将被覆盖。<br /></p> <span id="OSC_h4_11"></span> <h4>持久性</h4> <p>Put操作数据会存储在内存中的缓冲区称为memtable,也会选择性地插入到事务日志。每一个Put操作都有一组标志(通过WriteOptions设置),这些标志指定Put操作数据是否应该插入到事务日志。WriteOptions也可以指定在put操作提交前一个同步调用是否写入事务日志。在内部,RocksDB使用batch-commit机制批量写入事务日志,这样它可以使用一个同步调用提交多个事务。</p> <span id="OSC_h4_12"></span> <h4>容错</h4> <p>RocksDB使用校验和检测数据是否正确。每个块(通常是4k到128k大小)都有自己的校验和。一块数据一旦写入将不会修改。RocksDB通过硬件支持动态获取校验和的计算结果,以避免需要是自己计算校验和。</p> <span id="OSC_h4_13"></span> <h4>多线程Compaction</h4> <p>Compactions可以删除同一key的多个副本,副本是应用程序覆盖现有key是产生的,可以删除key。通过配置可以让Compaction以多线程方式运行。<br />LSM的写数据的整体吞吐量直接取决于Compaction的速度,特别是当数据存储在SSD或RAM这种存储器中。RocksDB可以处理多个线程并发的Comopaction请求。多线程Compaction场景下写数据的速率比单线程场景下的速率快10倍。<br />整个数据库存储在一组sstfiles。memtable写满时,它的内容会被写入Level-0层的一个文件中,在此过程中,重复和被覆盖的key会被删除。<br />一些文件被定期压缩合并形成更大的文件——这就是所谓的compaction。<br />RocksDB支持两种不同形式的compaction。普遍的做法是将所有文件按时间顺序保存在L0。compaction选择几个彼此相邻的文件并将它们合并成一个新文件L0。所有文件可以有重叠的key。分层形式的compaction将数据存储在数据库中的多个层中。最新的数据存储在L0和最旧的数据存储在Lmax。L0层中的文件可以有重叠的key,但其他层中文件的key不能重叠。一次compaction过程就是选择Ln层的一个文件及它在Ln+1层的所有重叠文件进行压缩合并形成Ln+1层的新文件。相比层形式的compaction方法,普遍的compaction方法写数据性能较低,但空间利用率较高。<br />MANIFEST文件记录了数据库的状态。compaction在添加新文件和从数据库删除现有的文件后,会将这些操作记录到MANIFEST文件。事务日志是被批量提交到MANIFEST文件中的,目的是为了减少对MANIFEST文件的重复同步访问。<br /><br /><br /><br /><br /></p> <span id="OSC_h4_14"></span> <h4>Compaction过滤器</h4> <p>一些应用程序可能需要在Compaction过程中处理某些key。例如,一个支持TTL的数据库可能删除过期的key,这可以通过定义一个Compaction过滤器完成。<br />如果应用程序想要不断删除旧数据,可以使用Compaction过滤掉丢弃过期的记录。RocksDB Compaction过滤器可以允许应用程序去修改对应key的value或作为Compaction过程的一部分直接丢弃key。<br /></p> <span id="OSC_h4_15"></span> <h4>只读的模式</h4> <p>数据库可以在只读的模式下打开。只读模式下应用程序不能修改任何数据。这可以保证更高的读取性能,因为避免了代码执行路径的切换和锁的使用。</p> <span id="OSC_h4_16"></span> <h4>数据库调试日志</h4> <p>RocksDB的详细日志被写入到名为LOG*的文件中。这些日志用于调试和分析运行中的系统。可以按配置的指定周期记录日志。</p> <span id="OSC_h4_17"></span> <h4>数据压缩</h4> <p>RocksDB支持snappy,zlib,bzip2 lz4和lz4_hc压缩算法。对不同层的数据可以配置不同的压缩算法。一般来说,90%的数据保存在Lmax层。<br />一个典型的安装可能是L0-L2层不配置压缩算法,中间层用snappy压缩算法,而Lmax层采用zlib压缩。<br /></p> <span id="OSC_h4_18"></span> <h4>事务日志</h4> <p>RocksDB将事务日志保存在logfile文件中以防止系统崩溃。系统启动时会重新处理日志文件。logfile和_sstfile_s可以存放在不同目录下,比如下面的场景,<br />当你希望将所有数据文件存储在非持久但快速的存储设备中,同时把事务日志保存在存取速度慢但持久的存储设备中。<br /></p> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/4393724/blog/3237971</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/zlib" hreflang="zh-hans">zlib</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/lz4" hreflang="zh-hans">lz4</a></div> <div class="field--item"><a href="/tag/rocksdb" hreflang="zh-hans">rocksdb</a></div> <div class="field--item"><a href="/tag/snappy" hreflang="zh-hans">snappy</a></div> <div class="field--item"><a href="/tag/c-0" hreflang="zh-hans">c++</a></div> <div class="field--item"><a href="/tag/hdfs" hreflang="zh-hans">HDFS</a></div> <div class="field--item"><a href="/tag/bzip2" hreflang="zh-hans">bzip2</a></div> </div> </div> Fri, 17 Apr 2020 00:25:31 +0000 人盡茶涼 3579845 at https://www.e-learn.cn 聊聊storm trident的state https://www.e-learn.cn/topic/865748 <span>聊聊storm trident的state</span> <span><span lang="" about="/user/54" typeof="schema:Person" property="schema:name" datatype="">↘锁芯ラ</span></span> <span>2019-12-01 02:11:09</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <h2>序</h2> <p>本文主要研究一下storm trident的state</p> <h2>StateType</h2> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/StateType.java</p> <pre><code>public enum StateType { NON_TRANSACTIONAL, TRANSACTIONAL, OPAQUE } </code></pre> <ul><li>StateType有三种类型,NON_TRANSACTIONAL非事务性,TRANSACTIONAL事务性,OPAQUE不透明事务</li> <li>对应的spout也有三类,non-transactional、transactional以及opaque transactional</li> </ul><h2>State</h2> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/State.java</p> <pre><code>/** * There's 3 different kinds of state: * * 1. non-transactional: ignores commits, updates are permanent. no rollback. a cassandra incrementing state would be like this 2. * repeat-transactional: idempotent as long as all batches for a txid are identical 3. opaque-transactional: the most general kind of state. * updates are always done based on the previous version of the value if the current commit = latest stored commit Idempotent even if the * batch for a txid can change. * * repeat transactional is idempotent for transactional spouts opaque transactional is idempotent for opaque or transactional spouts * * Trident should log warnings when state is idempotent but updates will not be idempotent because of spout */ // retrieving is encapsulated in Retrieval interface public interface State { void beginCommit(Long txid); // can be null for things like partitionPersist occuring off a DRPC stream void commit(Long txid); } </code></pre> <ul><li>non-transactional,忽略commits,updates是持久的,没有rollback,cassandra的incrementing state属于这个类型;at-most或者at-least once语义</li> <li>repeat-transactional,简称transactional,要求不管是否replayed,同一个batch的txid始终相同,而且里头的tuple也不变,一个tuple只属于一个batch,各个batch之间不会重叠;对于state更新来说,replay遇到相同的txid,即可跳过;在数据库需要较少的state,但是容错性较差,保证exactly once语义</li> <li>opaque-transactional,简称opaque,是用的比较多的一类,它的容错性比transactional强,它不要求一个tuple始终在同一个batch/txid,也就是说允许一个tuple在这个batch处理失败,但是在其他batch中处理成功,但是它可以保证每个tuple只在某一个batch中exactly成功处理一次;OpaqueTridentKafkaSpout就是这个类型的实现,它能容忍kafka节点丢失的错误;对于state更新来说,replay遇到相同的txid,则需要基于prevValue使用当前的值覆盖掉;在数据库需要更多空间来存储state,但是容错性好,保证exactly once语义</li> </ul><h2>MapState</h2> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/map/MapState.java</p> <pre><code>public interface MapState&lt;T&gt; extends ReadOnlyMapState&lt;T&gt; { List&lt;T&gt; multiUpdate(List&lt;List&lt;Object&gt;&gt; keys, List&lt;ValueUpdater&gt; updaters); void multiPut(List&lt;List&lt;Object&gt;&gt; keys, List&lt;T&gt; vals); } </code></pre> <ul><li>MapState继承了ReadOnlyMapState接口,而ReadOnlyMapState则继承了State接口</li> <li>这里主要举MapState的几个实现类分析一下</li> </ul><h3>NonTransactionalMap</h3> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/map/NonTransactionalMap.java</p> <pre><code>public class NonTransactionalMap&lt;T&gt; implements MapState&lt;T&gt; { IBackingMap&lt;T&gt; _backing; protected NonTransactionalMap(IBackingMap&lt;T&gt; backing) { _backing = backing; } public static &lt;T&gt; MapState&lt;T&gt; build(IBackingMap&lt;T&gt; backing) { return new NonTransactionalMap&lt;T&gt;(backing); } @Override public List&lt;T&gt; multiGet(List&lt;List&lt;Object&gt;&gt; keys) { return _backing.multiGet(keys); } @Override public List&lt;T&gt; multiUpdate(List&lt;List&lt;Object&gt;&gt; keys, List&lt;ValueUpdater&gt; updaters) { List&lt;T&gt; curr = _backing.multiGet(keys); List&lt;T&gt; ret = new ArrayList&lt;T&gt;(curr.size()); for (int i = 0; i &lt; curr.size(); i++) { T currVal = curr.get(i); ValueUpdater&lt;T&gt; updater = updaters.get(i); ret.add(updater.update(currVal)); } _backing.multiPut(keys, ret); return ret; } @Override public void multiPut(List&lt;List&lt;Object&gt;&gt; keys, List&lt;T&gt; vals) { _backing.multiPut(keys, vals); } @Override public void beginCommit(Long txid) { } @Override public void commit(Long txid) { } } </code></pre> <ul><li>NonTransactionalMap包装了IBackingMap,beginCommit及commit方法都不做任何操作</li> <li>multiUpdate方法构造List&lt;T&gt; ret,然后使用IBackingMap的multiPut来实现</li> </ul><h3>TransactionalMap</h3> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/map/TransactionalMap.java</p> <pre><code>public class TransactionalMap&lt;T&gt; implements MapState&lt;T&gt; { CachedBatchReadsMap&lt;TransactionalValue&gt; _backing; Long _currTx; protected TransactionalMap(IBackingMap&lt;TransactionalValue&gt; backing) { _backing = new CachedBatchReadsMap(backing); } public static &lt;T&gt; MapState&lt;T&gt; build(IBackingMap&lt;TransactionalValue&gt; backing) { return new TransactionalMap&lt;T&gt;(backing); } @Override public List&lt;T&gt; multiGet(List&lt;List&lt;Object&gt;&gt; keys) { List&lt;CachedBatchReadsMap.RetVal&lt;TransactionalValue&gt;&gt; vals = _backing.multiGet(keys); List&lt;T&gt; ret = new ArrayList&lt;T&gt;(vals.size()); for (CachedBatchReadsMap.RetVal&lt;TransactionalValue&gt; retval : vals) { TransactionalValue v = retval.val; if (v != null) { ret.add((T) v.getVal()); } else { ret.add(null); } } return ret; } @Override public List&lt;T&gt; multiUpdate(List&lt;List&lt;Object&gt;&gt; keys, List&lt;ValueUpdater&gt; updaters) { List&lt;CachedBatchReadsMap.RetVal&lt;TransactionalValue&gt;&gt; curr = _backing.multiGet(keys); List&lt;TransactionalValue&gt; newVals = new ArrayList&lt;TransactionalValue&gt;(curr.size()); List&lt;List&lt;Object&gt;&gt; newKeys = new ArrayList(); List&lt;T&gt; ret = new ArrayList&lt;T&gt;(); for (int i = 0; i &lt; curr.size(); i++) { CachedBatchReadsMap.RetVal&lt;TransactionalValue&gt; retval = curr.get(i); TransactionalValue&lt;T&gt; val = retval.val; ValueUpdater&lt;T&gt; updater = updaters.get(i); TransactionalValue&lt;T&gt; newVal; boolean changed = false; if (val == null) { newVal = new TransactionalValue&lt;T&gt;(_currTx, updater.update(null)); changed = true; } else { if (_currTx != null &amp;&amp; _currTx.equals(val.getTxid()) &amp;&amp; !retval.cached) { newVal = val; } else { newVal = new TransactionalValue&lt;T&gt;(_currTx, updater.update(val.getVal())); changed = true; } } ret.add(newVal.getVal()); if (changed) { newVals.add(newVal); newKeys.add(keys.get(i)); } } if (!newKeys.isEmpty()) { _backing.multiPut(newKeys, newVals); } return ret; } @Override public void multiPut(List&lt;List&lt;Object&gt;&gt; keys, List&lt;T&gt; vals) { List&lt;TransactionalValue&gt; newVals = new ArrayList&lt;TransactionalValue&gt;(vals.size()); for (T val : vals) { newVals.add(new TransactionalValue&lt;T&gt;(_currTx, val)); } _backing.multiPut(keys, newVals); } @Override public void beginCommit(Long txid) { _currTx = txid; _backing.reset(); } @Override public void commit(Long txid) { _currTx = null; _backing.reset(); } } </code></pre> <ul><li>TransactionalMap采取的是CachedBatchReadsMap&lt;TransactionalValue&gt;,这里泛型使用的是TransactionalValue,beginCommit会设置当前的txid,重置_backing,commit的时候会重置txid,然后重置_backing</li> <li>multiUpdate方法中判断如果_currTx已经存在值,且该值!retval.cached(<code>即不是本次事务中multiPut进去的</code>),那么不会更新该值(<code>skip the update</code>),使用newVal = val</li> <li>multiPut方法构造批量的TransactionalValue,然后使用CachedBatchReadsMap.multiPut(List&lt;List&lt;Object&gt;&gt; keys, List&lt;T&gt; vals)方法,该方法更新值之后会更新到缓存</li> </ul><h3>OpaqueMap</h3> <p>storm-2.0.0/storm-client/src/jvm/org/apache/storm/trident/state/map/OpaqueMap.java</p> <pre><code>public class OpaqueMap&lt;T&gt; implements MapState&lt;T&gt; { CachedBatchReadsMap&lt;OpaqueValue&gt; _backing; Long _currTx; protected OpaqueMap(IBackingMap&lt;OpaqueValue&gt; backing) { _backing = new CachedBatchReadsMap(backing); } public static &lt;T&gt; MapState&lt;T&gt; build(IBackingMap&lt;OpaqueValue&gt; backing) { return new OpaqueMap&lt;T&gt;(backing); } @Override public List&lt;T&gt; multiGet(List&lt;List&lt;Object&gt;&gt; keys) { List&lt;CachedBatchReadsMap.RetVal&lt;OpaqueValue&gt;&gt; curr = _backing.multiGet(keys); List&lt;T&gt; ret = new ArrayList&lt;T&gt;(curr.size()); for (CachedBatchReadsMap.RetVal&lt;OpaqueValue&gt; retval : curr) { OpaqueValue val = retval.val; if (val != null) { if (retval.cached) { ret.add((T) val.getCurr()); } else { ret.add((T) val.get(_currTx)); } } else { ret.add(null); } } return ret; } @Override public List&lt;T&gt; multiUpdate(List&lt;List&lt;Object&gt;&gt; keys, List&lt;ValueUpdater&gt; updaters) { List&lt;CachedBatchReadsMap.RetVal&lt;OpaqueValue&gt;&gt; curr = _backing.multiGet(keys); List&lt;OpaqueValue&gt; newVals = new ArrayList&lt;OpaqueValue&gt;(curr.size()); List&lt;T&gt; ret = new ArrayList&lt;T&gt;(); for (int i = 0; i &lt; curr.size(); i++) { CachedBatchReadsMap.RetVal&lt;OpaqueValue&gt; retval = curr.get(i); OpaqueValue&lt;T&gt; val = retval.val; ValueUpdater&lt;T&gt; updater = updaters.get(i); T prev; if (val == null) { prev = null; } else { if (retval.cached) { prev = val.getCurr(); } else { prev = val.get(_currTx); } } T newVal = updater.update(prev); ret.add(newVal); OpaqueValue&lt;T&gt; newOpaqueVal; if (val == null) { newOpaqueVal = new OpaqueValue&lt;T&gt;(_currTx, newVal); } else { newOpaqueVal = val.update(_currTx, newVal); } newVals.add(newOpaqueVal); } _backing.multiPut(keys, newVals); return ret; } @Override public void multiPut(List&lt;List&lt;Object&gt;&gt; keys, List&lt;T&gt; vals) { List&lt;ValueUpdater&gt; updaters = new ArrayList&lt;ValueUpdater&gt;(vals.size()); for (T val : vals) { updaters.add(new ReplaceUpdater&lt;T&gt;(val)); } multiUpdate(keys, updaters); } @Override public void beginCommit(Long txid) { _currTx = txid; _backing.reset(); } @Override public void commit(Long txid) { _currTx = null; _backing.reset(); } static class ReplaceUpdater&lt;T&gt; implements ValueUpdater&lt;T&gt; { T _t; public ReplaceUpdater(T t) { _t = t; } @Override public T update(Object stored) { return _t; } } } </code></pre> <ul><li>OpaqueMap采取的是CachedBatchReadsMap&lt;OpaqueValue&gt;,这里泛型使用的是OpaqueValue,beginCommit会设置当前的txid,重置_backing,commit的时候会重置txid,然后重置_backing</li> <li>与TransactionalMap的不同,这里在multiPut的时候,使用的是ReplaceUpdater,然后调用multiUpdate强制覆盖</li> <li>multiUpdate方法与TransactionalMap的不同,它是基于prev值来进行update的,算出newVal</li> </ul><h2>小结</h2> <ul><li>trident严格按batch的顺序更新state,比如txid为3的batch必须在txid为2的batch处理完之后才能处理</li> <li>state分三种类型,分别是non-transactional、transactional、opaque transactional,对应的spout也是这三种类型 <ul><li>non-transactional无法保证exactly once,它可能是at-least once或者at-most once;其state计算参考NonTransactionalMap,对于beginCommit及commit操作都无处理</li> <li>transactional类型能够保证exactly once,但是要求比较严格,要同一个batch的txid及tuple在replayed的时候仍然保持一致,因此容错性差一点,但是它的state计算相对简单,参考TransactionalMap,遇到同一个txid的值,skip掉即可</li> <li>opaque transactional类型也能够保证exactly once,它允许一个tuple处理失败之后,出现在其他batch中处理,因而容错性好,但是state计算要多存储prev值,参考OpaqueMap,遇到同一个txid的值,使用prev值跟当前值进行覆盖</li> </ul></li> <li>trident将保证exactly once的state的计算都封装好了,使用的时候,在persistentAggregate传入相应的StateFactory即可,支持多种StateType的factory可以选择使用StateType属性,通过传入不同的参数构造不同transactional的state;也可以通过实现StateFactory自定义实现state factory,另外也可以通过继承BaseQueryFunction来自定义stateQuery查询,自定义更新的话,可以继承BaseStateUpdater,然后通过partitionPersist传入</li> </ul><h2>doc</h2> <ul><li><a href="https://storm.apache.org/releases/2.0.0-SNAPSHOT/Trident-tutorial.html" rel="nofollow">Trident Tutorial</a></li> <li><a href="http://storm.apache.org/releases/2.0.0-SNAPSHOT/Trident-state.html" rel="nofollow">Trident State</a></li> </ul><div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/2922256/blog/2436027</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/storm-trident" hreflang="zh-hans">Storm Trident</a></div> <div class="field--item"><a href="/tag/multiget" hreflang="zh-hans">MultiGet</a></div> <div class="field--item"><a href="/tag/trident" hreflang="zh-hans">Trident</a></div> <div class="field--item"><a href="/tag/apache-storm" hreflang="zh-hans">Apache Storm</a></div> <div class="field--item"><a href="/tag/opaque" hreflang="zh-hans">Opaque</a></div> </div> </div> Sat, 30 Nov 2019 18:11:09 +0000 ↘锁芯ラ 865748 at https://www.e-learn.cn