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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lucene join解决父子关系索引

發布時間:2025/4/5 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lucene join解决父子关系索引 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://yq.aliyun.com/articles/20

1 背景

? ? ? ?以商家(Poi)維度來展示各種服務(比如團購(deal)、直連)正變得越來越流行(圖1a), 比如目前美食、酒店等品類在移動端將團購信息列表改為POI列表頁展示。?

? ? ? ? ? ? ? ? ?

圖1 ? a:商家維度展示信息; b:join示意 ? ?

?? ? ??這給篩選帶來了復雜性。之前的篩選是平面的,如篩選poi列表時僅僅利用到poi的屬性(如評價、品類等),篩選deal列表時也僅僅根據deal的屬性(房態、價格等)。而現在的篩選是具有層次關系的,我們需要根據deal的屬性來篩選Poi,舉個例子,我們需要篩選酒店列表,這些酒店必須要有價格在100~200之間的團購。

?? ? ??這種篩選本質是種join操作,其核心是要將poi與deal關聯起來。從數據庫視角上看(圖1 b),我們有poi表以及deal表,deal表存儲了外鍵(parentid)用于指示該deal所屬的poi,上述篩選分為三步:1)先篩選出價格區間在100~200的deal(得到dealid為2和3的deal);2)找出deal對應的poi(得到poiid為1和1的poi);3)去重,因為可能多個deal對應同一個poi,而我們需要返回不重復poi。

? ? ? ?目前我們使用lucene來提供篩選服務,那么lucene如何解決這種帶有join的篩選呢??

2 lucene join解決方案

? ? ? ?在我們應用中,一個poi存儲為一個document,一個deal也存儲為一個document,Join的核心在于將poi以及deal的document進行關聯。lucene提供了兩種join的方式,分別是query time join和index time join,下文將分別展開。

2.1. query time join

? ??? query time join是通過類似數據庫“外鍵“方法來建立deal和poi document的關聯關系。

?a)索引

?? ? ?分別創建poi的document和deal的document,在建立deal document的時候用一個字段(parentid)將deal與poi關聯起來,本例中創建了parentid這個field,里面存的是該deal對應的poiid,可以簡單將其看做外鍵。

1 2 3 4 5 6 public?static?Document createPoiDocument(PoiMsg poiMsg) { ???Document document =?new?Document(); ???document.add(new?StringField("poiid", String.valueOf(poiMsg.getId()), Field.Store.YES)); ???document.add(new?StringField("name", poiMsg.getName(), Field.Store.YES)); ???return?document; }

  

1 2 3 4 5 6 7 8 public?static?Document createDealDocument(DealModel dealModel, PoiMsg poiMsg) { ???Document document =?new?Document(); ???document.add(new?StringField("did", String.valueOf(dealModel.getDid()), Field.Store.YES)); ???document.add(new?StringField("name", dealModel.getBrandName(), Field.Store.YES)); ???document.add(new?DoubleField("price", dealModel.getPrice(), Field.Store.YES)); ???document.add(new?StringField("parentid", String.valueOf(poiMsg.getId()), Field.Store.YES)); ???return?document; }

  

1 2 3 4 5 6 IndexWriter writer =?new?IndexWriter(directory, config); writer.addDocument(createPoiDocument(poiMsg1)); writer.addDocument(createPoiDocument(poiMsg2)); writer.addDocument(createDealDocument(dealModel1, poiMsg2)); writer.addDocument(createDealDocument(dealModel2, poiMsg1)); writer.addDocument(createDealDocument(dealModel3, poiMsg1));

  

b)查詢

?? ? ?需查詢兩次:首先查詢deal document,之后通過deal中的parentId查詢poi document。

? ? ?1)第一次查詢發生在JoinUtil.createJoinQuery中。首先創建了TermsCollector這個收集器, 該收集器將滿足fromQuery的doc的parentid字段收集起來,之后創建了TermsQuery。

?? ? ? ? ?本例執行之后TermsCollector集合里有兩個terms,分別是”1”和”1”

? ? ?2)執行TermsQuery,查詢toField在TermsCollector terms集合中存在的doc,最后找出toField為“1”的doc。

1 2 3 4 5 6 IndexSearcher indexSearcher =?new?IndexSearcher(indexReader); ????????String fromFields =?"parentid"; ????????Query fromQuery = NumericRangeQuery.newIntRange("price",?100,?200,?false,?false); ????????String toFields =?"poiid"; ????????Query toQuery = JoinUtil.createJoinQuery(fromFields,?false, toFields, fromQuery, indexSearcher, ScoreMode.Max); ????????TopDocs results = indexSearcher.search(toQuery,?10);

  

1 2 3 4 JoinUtil.createJoinQuery代碼 ?TermsCollector termsCollector = TermsCollector.create(fromField, multipleValuesPerDocument); ?fromSearcher.search(fromQuery, termsCollector); ?return?new?TermsQuery(toField, fromQuery, termsCollector.getCollectorTerms());

  

c)優缺點

?? ? ??query time join優點是非常直觀且靈活;缺點是不能進行打分排序,此外由于查詢兩遍性能會下降。

2.2. index time join

?? ? ? ?query time join通過顯式的在deal document上增加一個“外鍵”來建立關系,找到deal之后需要找出這些deal document的parentid集合,之后再次查詢找出poiId在parentid集合內的poi document。在找到deal之后如果能馬上找到對應的poi document,那將大大提高效率。index time join干的就是這樣的事情,其通過一種精巧的方法建立了deal document id和poi document id的映射關系。

a)原理

?? ? ?如何通過一個deal document id來找到poi document id?

?? ? ?在lucene中,doc id是自增的,每寫入一個document,doc id加1(簡單起見可以理解)。?index time join要求寫索引的時候要按先后關系寫入,先寫子document,再寫父document。比如我們有poi1和poi2兩個poi,其中poi1下有deal2和deal3,而poi2下只有deal1,這時需要先寫入deal2、deal3,再寫入deal2和deal3對應的poi1 document,依次類推,最后形成如圖2所示的結構。

?? ? ?這樣索引建立之后,我們得到了父document的id集合(3,5)。當我們根據deal的屬性查出deal document id時,比如我們查出滿足條件的deal是deal3,其document id=2,這時候只需要到父document id集合里去查找第一個比2大的id,在本例中馬上就找到3。

圖2?

? ? ?lucene自己實現了BitSet來保存id,lucene內部實現代碼如圖3所示。

圖3 實現原理

b)索引

?? ? ? 從上述原理得知我們需要建立有層次關系的索引。

?? ? ??首先創建document數組,該數組有個特點, 最后一個必須是poi,之前都是deal。然后調用writer.addDocument(documents); 將這個數組寫入。

1 2 3 4 5 6 7 public?static?Document createPoiDocument(PoiMsg poiMsg) { ????????Document document =?new?Document(); ????????document.add(new?StringField("poiid", String.valueOf(poiMsg.getId()), Field.Store.YES)); ????????document.add(new?StringField("name", poiMsg.getName(), Field.Store.YES)); ????????document.add(new?StringField("doctype",?"poi", Field.Store.YES)); ????????return?document; ????}

  

1 2 3 4 5 6 7 public?static?Document createDealDocument(DealModel dealModel) { ????????Document document =?new?Document(); ????????document.add(new?StringField("did", String.valueOf(dealModel.getDid()), Field.Store.YES)); ????????document.add(new?StringField("name", dealModel.getBrandName(), Field.Store.YES)); ????????document.add(new?DoubleField("price", dealModel.getPrice(), Field.Store.YES)); ????????return?document; ????}

  

1 2 3 4 5 6 7 8 9 10 IndexWriter writer =?new?IndexWriter(directory, config); List<Document> documents =?new?ArrayList<Document>(); documents.add(createDealDocument(dealModel2)); documents.add(createDealDocument(dealModel3)); documents.add(createPoiDocument(poiMsg1)); writer.addDocument(documents); documents.clear(); documents.add(createDealDocument(dealModel1)); documents.add(createPoiDocument(poiMsg2)); writer.addDocument(documents);

c)查詢

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Filter poiFilter =?new?CachingWrapperFilter(new?QueryWrapperFilter(new?TermQuery(new?Term(PoiLuceneField.ATTR_DOCTYPE,?"poi"))));?//篩選出poi ToParentBlockJoinQuery query =?new?ToParentBlockJoinQuery(dealQuery, poiFilter, ScoreMode.Max); ToParentBlockJoinCollector collector =?new?ToParentBlockJoinCollector( ????????????????????sort,?// sort ????????????????????(getOffset() + getLimit()),?????????????// poi分頁numHits ????????????????????true,???????????// trackScores ????????????????????false???????????// trackMaxScore ????????????); collector = (ToParentBlockJoinCollector) indexSearcher.search(query, collector); Sort childSort =?new?Sort(new?SortField(DealLuceneField.ATTR_PRICE, SortField.Type.DOUBLE)); TopGroups hits = collector.getTopGroups( ????????????????????query.getToParentBlockJoinQuery(), ????????????????????childSort, ????????????????????query.getOffset(),???// parent doc offset ????????????????????100,??// maxDocsPerGroup ????????????????????0,???// withinGroupOffset ????????????????????true?// fillSortFields ????????????);

  

3 實踐

? ? ?官方文檔顯示index time join效率更高,比query time join快30%以上。因此我們在項目中使用了index time join方式,目前服務運行良好。

轉載于:https://www.cnblogs.com/davidwang456/articles/10045715.html

總結

以上是生活随笔為你收集整理的lucene join解决父子关系索引的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 又爽又黄又无遮挡 | 可以在线看黄的网站 | 久久久精品久久久久 | 欧美成人三级精品 | 亚洲涩涩爱| 免费av电影网址 | 黑人巨大av | 成人在线观看一区二区三区 | 黄色激情小说视频 | 欧美日韩女优 | 男女交性视频 | av直播在线观看 | 精品人妻久久久久一区二区三区 | 免费观看视频在线观看 | 伊人五月婷婷 | 美女福利在线视频 | 亚洲AV无码成人精品区先锋 | 水牛影视av一区二区免费 | 伊人一级 | 综合久久伊人 | 夜间福利在线 | 日本在线天堂 | 欧美视频一二区 | 91超碰在线播放 | 国产精成人 | 黄色av网| 欧美一级特黄aaaaaa大片在线观看 | 97人人模人人爽人人少妇 | 综合欧美亚洲 | 一本一道久久综合 | 精品一区二区三区四区视频 | 制服丝袜一区 | 黄色aa毛片 | 被灌满精子的波多野结衣 | 在线观看免费 | 中文字幕被公侵犯的漂亮人妻 | 欧美在线一区二区三区四区 | 男女午夜啪啪 | 国产小视频在线观看 | www.黄色片| 亚洲乱色熟女一区二区三区 | 床戏高潮做进去大尺度视频网站 | 公交顶臀绿裙妇女配视频 | 免费观看黄色网址 | 久久久久久久久久久久国产精品 | 伊朗做爰xxxⅹ性视频 | 久久青草免费视频 | 国产精品久久久久久久久久久免费看 | 日本aⅴ在线观看 | 成人亚洲精品 | 日韩三级在线播放 | 极品美女av| 亚洲网av| 亚洲国产精彩视频 | 国产成人精品一区二区在线小狼 | 男人操女人下面视频 | 九色影视| 欧美国产日韩一区二区 | 永久看看免费大片 | 亚洲视频一区在线 | www久久 | 德国性经典xxxx性hd | 日本天天色 | 五月激情综合婷婷 | 欧美r级在线观看 | 亚洲精品高清在线 | 精品少妇av| 欧美成人午夜精品免费 | 黄色av网站免费 | 亚洲精品国产精品乱码在线观看 | 亚洲综合色成人 | 胸网站| 99草视频 | 亚洲第一欧美 | 欧美另类专区 | 久久国产主播 | 激情婷婷丁香 | 欧美女人一区二区 | 4438国产精品一区二区 | 中文字幕乱码视频 | 亚洲精品乱码久久久久久国产主播 | 亚洲永久免费精品 | 天天操操操操操 | 精品一区二区三区入口 | 成年人视频在线看 | 黄色图片小说 | 欧美午夜激情视频 | 九九九久久久久 | 91大神在线观看视频 | 久久久999久久久 | 少妇裸体挤奶汁奶水视频 | 国产精品情侣呻吟对白视频 | 日本成人在线网站 | 91成人天堂久久成人 | 成人av图片 | 男人插女人免费视频 | 性猛交娇小69hd | 中文字幕乱码中文乱码777 | 成人精品网址 |