日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Elasticsearch中如何进行排序(中文+父子文档+嵌套文档)

發(fā)布時(shí)間:2025/7/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch中如何进行排序(中文+父子文档+嵌套文档) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Elasticsearch中如何進(jìn)行排序

背景

最近去兄弟部門(mén)的新自定義查詢(xún)項(xiàng)目組搬磚,項(xiàng)目使用Elasticsearch進(jìn)行數(shù)據(jù)的檢索和查詢(xún)。每一個(gè)查詢(xún)頁(yè)面都需要根據(jù)選擇的字段進(jìn)行排序,以為是一個(gè)比較簡(jiǎn)單的需求,其實(shí)實(shí)現(xiàn)起來(lái)還是比較復(fù)雜的。這里進(jìn)行一個(gè)總結(jié),加深一下記憶。

前置知識(shí)

  • Elasticsearch是什么?
    Elasticsearch 簡(jiǎn)稱(chēng)ES,是一個(gè)全文搜索引擎,可以實(shí)現(xiàn)類(lèi)似百度搜索的功能。但她不僅僅能進(jìn)行全文檢索,還可以實(shí)現(xiàn)PB級(jí)數(shù)據(jù)的近實(shí)時(shí)分析和精確查找,還可以作GIS數(shù)據(jù)庫(kù),進(jìn)行AI機(jī)器學(xué)習(xí),功能非常強(qiáng)大。

  • ES的數(shù)據(jù)模型
    ES中常用嵌套文檔父子文檔兩種方法進(jìn)行數(shù)據(jù)建模,多層父子文檔還可以形成祖孫文檔。但是父子文檔是一種不推薦的建模方式,這種方式有很多的局限性。如果傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的建模方法是通過(guò)“三范式”進(jìn)行規(guī)范化,那么ES的建模方法就是反范式,進(jìn)行反規(guī)范化。關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)是表格模型,ES是JSON樹(shù)狀模型。

ES中排序的分類(lèi)

根據(jù)建模方法的不同,ES中排序分為以下幾種,每種都有不同的排序?qū)懛ê鸵恍┫拗?#xff1a;

  • 嵌套文檔-根據(jù)主文檔字段排序
  • 嵌套文檔-根據(jù)內(nèi)嵌文檔字段排序
  • 父子文檔-查父文檔然后根據(jù)子文檔排序
  • 父子文檔-查子文檔然后根據(jù)父文檔排序
  • 更復(fù)雜的情況,父子文檔里又嵌套了文檔,然后根據(jù)嵌套文檔字段進(jìn)行排序。

下面分別對(duì)其中某幾種情況和中文字段的排序,進(jìn)行測(cè)試說(shuō)明(ES 5.5.x)。

測(cè)試數(shù)據(jù)準(zhǔn)備

首先,設(shè)置索引類(lèi)型字段映射

PUT /test_sort {"mappings": {"zf":{"properties": {"id":{"type": "keyword"},"name":{"type": "keyword"},"age":{"type": "integer"},"shgx":{"type": "nested"}}}} }

然后新建測(cè)試數(shù)據(jù)

PUT /test_sort/zf/1 {"id":1,"name":"張三","age":18,"shgx":[{"id":1,"name":"老張","age":50,"gx":"父親"},{"id":2,"name":"張二","age":22,"gx":"哥哥"}] }PUT /test_sort/zf/2 {"id":2,"name":"李四","age":25,"shgx":[{"id":3,"name":"李五","age":23,"gx":"弟弟"}] }
  • 嵌套文檔-根據(jù)主文檔字段排序
    根據(jù)zf主文檔age字段倒敘排列,直接加sort子語(yǔ)句就可以
POST /test_sort/zf/_search {"query": {"match_all": {}},"sort": [{"age": {"order": "desc"}}],"_source": {"include": ["id","name","age"]} }

結(jié)果:

"hits": [{"_index": "test_sort","_type": "zf","_id": "2","_score": null,"_source": {"name": "李四","id": 2,"age": 25},"sort": [25]},{"_index": "test_sort","_type": "zf","_id": "1","_score": null,"_source": {"name": "張三","id": 1,"age": 18},"sort": [18]}]
  • 嵌套文檔-根據(jù)內(nèi)嵌文檔字段排序
    根據(jù)age小于50歲的親屬排序,理論上李四應(yīng)該排第一位,因?yàn)?0歲以下的親屬,李五最大。 憑直覺(jué)先這樣寫(xiě):
POST /test_sort/zf/_search {"query": {"nested": {"path": "shgx","query": {"range": {"shgx.age": {"lt": 50}}}}},"sort": [{"shgx.age": {"nested_path": "shgx", "order": "desc"}}] }

看結(jié)果:

"hits": [{"_index": "test_sort","_type": "zf","_id": "1","_score": null,"_source": {"id": 1,"name": "張三","age": 18,"shgx": [{"id": 1,"name": "老張","age": 50,"gx": "父親"},{"id": 2,"name": "張二","age": 22,"gx": "哥哥"}]},"sort": [50]},{"_index": "test_sort","_type": "zf","_id": "2","_score": null,"_source": {"id": 2,"name": "李四","age": 25,"shgx": [{"id": 3,"name": "李五","age": 23,"gx": "弟弟"}]},"sort": [23]}]

非常重要!結(jié)果是錯(cuò)誤的。這是因?yàn)榍短孜臋n是作為主文檔的一部分返回的,在主查詢(xún)中的嵌套文檔的過(guò)濾條件并不能把不符合條件的內(nèi)部嵌套文檔過(guò)濾掉,返回的還是整個(gè)文檔(主文檔+完整的嵌套文檔)。以至于按嵌套文檔字段排序時(shí),還是按照全部的嵌套文檔進(jìn)行排序的。要正確的實(shí)現(xiàn)排序,就要把主查詢(xún)中有關(guān)嵌套文檔的查詢(xún)條件,在排序中再寫(xiě)一遍

正確的寫(xiě)法:

POST /test_sort/zf/_search {"query": {"nested": {"path": "shgx","query": {"range": {"shgx.age": {"lt": 50}}}}},"sort": [{"shgx.age": {"nested_path": "shgx", "order": "desc","nested_filter": {"range": {"shgx.age": {"lt": 50}}}}}] }
  • 父子文檔-查父文檔-根據(jù)子文檔排序
    構(gòu)造測(cè)試數(shù)據(jù),首先設(shè)置父子文檔的映射關(guān)系
PUT /test_sort_2 {"mappings": {"zf_parent":{"properties": {"id":{"type": "keyword"},"name":{"type": "keyword"},"age":{"type": "integer"}}},"shgx":{"_parent": {"type": "zf_partent"}}} }

然后,添加數(shù)據(jù)。

PUT /test_sort_2/zf_parent/1 {"id":1,"name":"張三","age":18 } PUT /test_sort_2/zf_parent/2 {"id":2,"name":"李四","age":25 }PUT /test_sort_2/shgx/1?parent=1 {"id":1,"name":"老張","age":50,"gx":"父親" }PUT /test_sort_2/shgx/2?parent=1 {"id":2,"name":"張二","age":22,"gx":"哥哥" }PUT /test_sort_2/shgx/3?parent=2 {"id":3,"name":"李五","age":23,"gx":"弟弟" }

然后,根據(jù)age小于50歲的親屬排序,升序的話(huà)張三應(yīng)該是第一位

POST /test_sort_3/zf_parent/_search {"query": {"has_child": {"type": "shgx","query": {"range": {"age": {"lt": 50}}},"inner_hits": {"name": "ZfShgx","sort": [{"age": {"order": "asc"}}]}}} }

查看排序結(jié)果:

{"_index": "test_sort_3","_type": "zf_parent","_id": "2","_score": 1,"_source": {"id": 2,"name": "李四","age": 25},"inner_hits": {"ZfShgx": {"hits": {"total": 1,"max_score": null,"hits": [{"_type": "shgx","_id": "3","_score": null,"_routing": "2","_parent": "2","_source": {"id": 3,"name": "李五","age": 23,"gx": "弟弟"},"sort": [23]}]}}}},{"_index": "test_sort_3","_type": "zf_parent","_id": "1","_score": 1,"_source": {"id": 1,"name": "張三","age": 18},"inner_hits": {"ZfShgx": {"hits": {"total": 1,"max_score": null,"hits": [{"_type": "shgx","_id": "2","_score": null,"_routing": "1","_parent": "1","_source": {"id": 2,"name": "張二","age": 22,"gx": "哥哥"},"sort": [22]}]}}}}

結(jié)果是錯(cuò)誤的,李四在前,查看官方文檔的父子文檔時(shí)不能直接用子文檔排序父文檔,或者用父文檔排序子文檔。那有沒(méi)有解決辦法呢?有一個(gè)曲線(xiàn)救國(guó)的方案,使用function_score通過(guò)子文檔的評(píng)分來(lái)影響父文檔的順序,但是評(píng)分算法很難做到精準(zhǔn)控制順序。

中文字符排序

在項(xiàng)目中發(fā)現(xiàn),中文字符在ES中的順序和在關(guān)系型數(shù)據(jù)庫(kù)中的順序不一致。經(jīng)查是因?yàn)镋S是用的unicode的字節(jié)碼做排序的。即先對(duì)字符(包括漢字)轉(zhuǎn)換成byte[]數(shù)組,然后對(duì)字節(jié)數(shù)組進(jìn)行排序。這種排序規(guī)則對(duì)ASIC碼(英文)是有效的,但對(duì)于中文等亞洲國(guó)家的字符不適用,怎么辦呢?有兩種解決辦法:

  • 第一種,做拼音冗余。即在向ES同步數(shù)據(jù)時(shí)候,同步程序?qū)h字字段同時(shí)轉(zhuǎn)換成拼音,在ES里專(zhuān)門(mén)用于漢字排序。如:
#插入信息 POST /test/star/1 {"xm": "劉德華","xm_pinyin": "liudehua" }POST /test/star/2 {"xm": "張惠妹","xm_pinyin": "zhanghuimei" }# 查詢(xún)排序 POST /test/star/_search {"query": {"match_all": {}},"sort": [{"xm_pinyin": {"order": "desc"}}] }
  • 第二種,使用ICU分詞插件。使用插件提供的icu_collation_keyword 映射類(lèi)型實(shí)現(xiàn)中文排序。
PUT test2 {"mappings": {"star": {"properties": {"xm": { "type": "text","fields": {"sort": { "type": "icu_collation_keyword","index": false,"language": "zh","country": "CN"}}}}}} }POST /test2/star/_search {"query": {"match_all": { }},"sort": "xm.sort" }

結(jié)論

  • 嵌套文檔-根據(jù)主文檔字段排序時(shí),可以使用sort語(yǔ)句直接排序,無(wú)限制。
  • 嵌套文檔-根據(jù)嵌套文檔字段排序時(shí),必須在sort子句里把所有嵌套相關(guān)的查詢(xún)條件,在sort里重新寫(xiě)一邊,排序才正確。
  • 父子文檔-查父文檔根據(jù)子文檔排序時(shí),不能根據(jù)子文檔排序父文檔,反之亦然。
  • 數(shù)據(jù)模型的復(fù)雜程度決定了排序的復(fù)雜程度,排序的復(fù)雜程度隨著模型的復(fù)雜程度成指數(shù)級(jí)增加。
  • 中文字符可以通過(guò)做拼音冗余和使用ICU插件來(lái)實(shí)現(xiàn)排序。

轉(zhuǎn)載于:https://www.cnblogs.com/wangzhen3798/p/9884054.html

總結(jié)

以上是生活随笔為你收集整理的Elasticsearch中如何进行排序(中文+父子文档+嵌套文档)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: www.午夜| a久久久久 | 青青操免费| 99re只有精品 | 少妇高潮一区二区三区 | 一区二区三区四区视频在线观看 | 69精品丰满人妻无码视频a片 | 日本免费在线一区 | 老熟妇毛茸茸 | 朝桐光一区二区三区 | av毛片网| av色片| 男性影院 | 亚洲女优一区 | 波多野结衣视频播放 | 91久久久久 | 我的大叔| 青青草在线免费视频 | 黄色片视频播放 | 国产又粗又黄又猛 | 91天天爽| 午夜福利一区二区三区 | 青青草视频在线看 | 久久精品超碰 | 阿娇全套94张未删图久久 | 久久视频精品在线 | 日韩美女一区 | 69视频在线播放 | 国产激情网站 | 精品婷婷色一区二区三区蜜桃 | 可以在线看黄的网站 | 亚洲女同视频 | 亚洲天堂中文字幕 | 精品欧美在线观看 | 精品视频亚洲 | 亚洲高清视频一区 | www国产亚洲精品久久麻豆 | 欧美操女人 | 奇米网久久 | 亚洲中文字幕无码一区二区三区 | 伊人称影院| 欧美孕交视频 | 国产一区视频免费观看 | 91综合国产 | 哪里看毛片 | 国产人妖一区二区 | 精品久久五月天 | 国产免费一区二区三区在线观看 | 韩日激情视频 | xxxxx在线观看 | 91网站观看 | 在线一区二区三区 | 国产午夜免费 | 女同中文字幕 | 亚洲av无码国产精品麻豆天美 | 日韩精品人妻一区 | 精品国产伦一区二区三区 | 欧美在线视频一区二区 | 久久久久久久极品内射 | 国产一级片av | 亚洲久久一区二区 | 成人免费毛片片v | www.久久久| 五十路毛片| 国产乱码精品一品二品 | 骚视频在线观看 | 香蕉视频网站入口 | 丰满秘书被猛烈进入高清播放在 | 97超级碰碰人妻中文字幕 | 免费欧美在线 | 成人久久网站 | 国产特级aaaaaa大片 | 91avcom | 日本国产高清 | 一级片少妇 | 亚洲精品二 | 少妇的激情 | 欧美 丝袜 自拍 制服 另类 | 特级av | 亚洲精品福利网站 | 福利社午夜| 欧美日韩国产成人 | 五月婷婷免费视频 | 亚洲一级片免费看 | 99er久久| 国产精品二区一区二区aⅴ污介绍 | 小柔好湿好紧太爽了国产网址 | 国产福利91精品一区二区三区 | 国产69xx| 日韩一级视频在线观看 | 国产一二三四五区 | 在线视频一区二区三区四区 | 中文字幕av专区 | 老头老夫妇自拍性tv | 饥渴丰满的少妇喷潮 | 国产精品一区二区毛片 | 福利视频一区二区 | 视频成人免费 | 成年女人毛片 |