標籤:solr mongodb json mongo-connector 嵌套對象
有一些東西記錄下來,不久之後就會再次用到。
1. 使複雜的嵌套對象從MongoDB更新到Solr
最近使用mongo-connector將MongoDB與Solr打通,對於簡單的json,更新是沒問題了。這次我們遇到的問題是,如果json中某一個field的值是數群組類型,或者有嵌套了一個對象,那該怎麼整。比如,我們在MongoDB中插入這麼個貨:
{ "_id": "555df36ec6cd08ea807a4324", "name": "小米手機", "comments": [ { "text": "手機是正品", }, { "text": "物流真他媽快", } ]}
這東西能同步到Solr嗎,我手心真是一把汗一把汗啊。經過多次嘗試,非常不幸,轟轟烈烈的失敗了。
無奈,去我們偉大的官方說明看一看吧,https://github.com/10gen-labs/mongo-connector/wiki/Usage%20with%20Solr ,其中有一段:Key Names and Document Flattening,尼瑪前幾天還沒有這段說明好不,真是坑爹啊。算了,不管怎樣,看起來這東西針對上面那種json還是有辦法的,按照說明,上面那段json應該轉換成以下形式:
{ "_id": "555df36ec6cd08ea807a4324", "name": "小米手機", "comments.0.text":"手機是正品", "comments.1.text":"物流真他媽快"}
然後提交給Solr。並且,我們從官方文檔中看不出來任何需要配置的地方,難道,預設安裝好,這些東西就能行?Oh,No~~~~
這是為什麼呢,我們看看官方對schema.xml的說明,原來關鍵點在這,大概意思就是mongo-connector會讀取這個設定檔,在將資料提交給Solr之前,會將資料中沒有在schema.xml中聲明的field去掉。
哦,原來如此,應該是形如"comments.0.text"這樣的field沒有被schemal.xml聲明,所以被去掉了,在Solr中見不到。那麼我們對症下藥,既然沒有聲明這個域,我們聲明不就好了,在schema.xml中加入:
<field name="comments.0.text" type="text_mmseg4j_complex" indexed="true" stored="true"/>
schema.xml的路徑參考上一篇文章。重啟Solr,保持mongo-connector開啟,重新往MongoDB中插入上面那段json,哇,ok,我們可以在Solr前端看到"comments.0.text"了,偉大的革命征程終於邁出了第一步!
成功之後,你可能還想顯示"comments.1.text",如法炮製。那麼,問題來了,如果我數組中有多個對象,無限多,難道我要把所有的可能field都聲明一遍?
這個問題問的真是極好的!我們不得不說schema.xml是個非常重要的東西!
這個時候,我們要用到在schemal.xml中的另外一種東西,dynamicField。這東西看起來可以通配多個名稱,按照已有的樣本。那麼,按照我們的需求,我們這樣添加:
<dynamicField name="comments*" type="text_mmseg4j_complex" indexed="true" stored="true"/>
這個意思很明顯了,就是聲明了所有通配comments*的域,這樣我們就可以把所有的comments*一網打盡了。
如果想進一步探究mongo-connector怎樣做到上面這些的,可以參考python檔案:
/usr/local/lib/python2.7/dist-packages/mongo_connector/doc_managers/solr_doc_manager.py
到這,我們就完成了更新這一偉大使命。
2. 在Solr中對嵌套對象及數組進行Query
按照1中所述,我們目前可以在Solr前端看到更新的欄位,並且,這些欄位已經被Solr建立索引,那麼我們該如何查詢他們呢,比如我們想用關鍵字“正品”在所有的形如"comments.*.text"的欄位中命中到“手機是正品”這個值。令人遺憾的是,Solr提供給我們值的各種查詢手段,卻不給我們指定目標field的各種手段,我們只是形如"comments.*.text",但事實上,我們並不能在Solr中這樣指定要搜尋的域。
這時,不得不再次說一句,schema.xml真特麼太重要了,我們用到了裡面又一個東西copyField。這個東西可以看看schema.xml中的注釋,大概意思就是建立索引時source的值可以加入到dest,反過來查詢dest也就同時能對source進行查詢,關鍵是多個source可以copy到一個dest啊,這不就正合我意嘛。說了這麼多,只需要我們在schema.xml中加入一句:
<copyField source="comments*" dest="text"/>
這個dest的field "text"一定要設定成multiValue="true"哦,不然mongo-connector會報錯的,想來應該也是吧,這麼多source到一個dest,別問我是怎麼知道的,這個確實是我試出來的,中間過程就不多說了。
按照上面所說,這個時候我們對text域進行尋找,就會去coments*域尋找,設定Solr的df為text,q為關鍵字,猛擊吧,騷年,你會得到想要的東西。
好了,碼了這麼多,關鍵點就是這麼多了,坑太多,小心小心呐~~
論mongo-connector如何將MongoDB中的json數組和嵌套對象更新至Solr引擎