2013-10-08 157 views
0

有沒有什麼辦法,我可以如何使Solr索引嵌入mongoDB文檔?我們已經可以通過mongo-connector索引mongo文檔中密鑰的頂級值,並將數據推送到Solr。索引嵌入式mongoDB文檔(在一個數組中)與Solr

但是,在像本結構,其表示後情況:

{ 
    author: "someone", 
    post_text : "some really long text which is already indexed by solr", 
    comments : [ 
     { 
      author:"someone else" 
      comment_text:"some quite long comment, which I do not 
          know how to index in Solr" 
     }, 
     { 
      author:"me" 
      comment_text:"another quite long comment, which I do not 
          know how to index in Solr" 
     } 
    ] 
} 

這僅僅是一個示例結構。在我們的項目中,我們處理更復雜的結構,有時,我們想要索引的文本嵌套在第二或第三層(深度,或者它的正式名稱)。

我相信有一個mongoDB + Solr用戶社區,所以這個問題一定是以前被提出過的,但是我找不到很好的材料,如果有一個很好的方法,將會覆蓋這個問題,處理這個問題,或者是否沒有解決方案和解決方法尚未建立(也許你可以提供給我一個)

爲了更好的理解,我們的結構之一有頂級的關鍵,其價值一些分析結果的陣列,其中一個分析結果具有一組奇異值,這些都是結果的一部分。我們需要對這些值進行索引。例如。 (這是不實際的數據結構,我們使用):

{... 
    Analysis_performed: [ 
     { 
      User_tags: 
       [ 
        { 
         tag_name: "awesome", 
         tag_score: 180 
        }, 
        { 
         tag_name: "boring", 
         tag_score: 10 
        } 
       ] 
     } 
    ] 
} 

在這種情況下,我們將需要指數的標記名稱。我們可能存在一個糟糕的存儲數據結構,我們想要存儲,但我們認真考慮了這一點,我們認爲它很好。但是,即使我們切換到嵌套較少的信息,我們也很可能會遇到至少一種情況,那就是我們必須索引存儲在數組中嵌入文檔中的信息,這是問題的主要焦點。我們可以用SOLR索引這些數據嗎?

回答

1

官方10gen mongo連接器現在支持數組展平和索引子文檔。 請參閱https://github.com/10gen-labs/mongo-connector

但是,對於數組,它做了一些不愉快的事情。這將這個文檔轉換:

{ 
    "hashtagEntities" : [ 
     { 
       "start" : "66", 
       "end" : "81", 
       "text" : "startupweekend" 
     }, 
     { 
       "start" : "82", 
       "end" : "90", 
       "text" : "startup" 
     }, 
     { 
       "start" : "91", 
       "end" : "100", 
       "text" : "startups" 
     }, 
     { 
       "start" : "101", 
       "end" : "108", 
       "text" : "london" 
     } 
    ] 
} 

到這一點:

{ 
    "hashtagEntities.0.start" : "66", 
    "hashtagEntities.0.end" : "81", 
    "hashtagEntities.0.text" : "startupweekend", 
    "hashtagEntities.1.start" : "82", 
    "hashtagEntities.1.end" : "90", 
    "hashtagEntities.1.text" : "startup", 
.... 
} 

以上是在Solr的指標非常困難 - 甚至更多,如果你有你的文件沒有穩定的架構。我們希望更多的東西是這樣的:

{ 
    "hashtagEntities.xArray.start": [ 
     "66", 
     "82", 
     "91", 
     "101" 
    ], 
    "hashtagEntities.xArray.text": [ 
     "startupweekend", 
     "startup", 
     "startups", 
     "london" 
    ], 
    "hashtagEntities.xArray.end": [ 
     "81", 
     "90", 
     "100", 
     "108" 
    ], 
} 

我已經實現了另solr_doc_manager.py

如果你想利用這一點,只需在您的doc_manager這個編輯flatten_doc功能,以支持這樣的功能:

def flattened(doc): 
    return dict(flattened_kernel(doc, [])) 
def flattened_kernel(doc, path): 
    for k, v in doc.items(): 
     path.append(k) 
     if isinstance(v, dict): 
      for inner_k, inner_v in flattened_kernel(v, path): 
       yield inner_k, inner_v 
     elif isinstance(v, list): 
      for inner_k, inner_v in flattened_list(v, path).items(): 
       yield inner_k, inner_v 
      path.pop() 
     else: 
      yield ".".join(path), v 
     path.pop()   
def flattened_list(v, path): 
    tem = dict() 
    #path2 = list() 
    path.append(str("xArray"))    
    for li, lv in enumerate(v):     
     if isinstance(lv, dict): 
      for dk, dv in flattened_kernel(lv, path): 
       got = tem.get(dk, list()) 
       if isinstance(dv, list): 
        got.extend(dv) 
       else: 
        got.append(dv) 
       tem[dk] = got 
     else: 
      got = tem.get(".".join(path)+".ROOT", list()) 
      if isinstance(lv, list): 
       got.extend(lv) 
      else: 
       got.append(lv) 
      tem[".".join(path)+".ROOT"] = got 
    return tem 

如果你不想丟失數組中的數據,這些數據不是子文件,這個實現會將數據放入一個「array.ROOT」屬性中。在這裏看到:

{ 
    "array" : [ 
      { 
        "innerArray" : [ 
          { 
            "c" : 1, 
            "d" : 2 
          }, 
          { 
            "ahah" : "asdf" 
          }, 
          42, 
          43 
        ] 
      }, 
      1, 
      2 
    ], 
} 

到:

{ 
    "array.xArray.ROOT": [ 
     "1.0", 
     "2.0" 
    ], 
    "array.xArray.innerArray.xArray.ROOT": [ 
     "42.0", 
     "43.0" 
    ], 
    "array.xArray.innerArray.xArray.c": [ 
     "1.0" 
    ], 
    "array.xArray.innerArray.xArray.d": [ 
     "2.0" 
    ], 
    "array.xArray.innerArray.xArray.ahah": [ 
     "asdf" 
    ] 
} 
1

幾個月前,我有這樣的問題。我的解決方案是使用doc_manager。 您可以使用solr_doc_manager(upsert方法)來修改發佈到solr中的文檔。舉例來說,如果你有

ACL: { 
    Read: [ id1, id2 ... ] 
} 

,你可以處理它像

def upsert(self, doc): 
    if ("ACL" in doc) and ("Read" in doc["ACL"]): 
     doc["ACL.Read"] = [] 
     for item in doc["ACL"]["Read"]: 
      if not isinstance(item, dict): 
       id = ObjectId(item) 
       doc["ACL.Read"].append(str(id)) 
    self.solr.add([doc], commit=False) 

它增加了新的領域 - ACL.Read。這個字段是多值的,並存儲來自ACL的ID列表:{讀:[012]

如果您不想爲嵌套文檔編寫自己的處理程序,則可以嘗試另一個mongo連接器。 Github項目頁面https://github.com/SelfishInc/solr-mongo-connector。它支持嵌入式文檔。

+0

因此,我們正考慮在生產環境中使用此連接器 - 您認爲該項目是否可靠並可靠?它在生產的其他地方使用嗎? – Ev0oD

0

我有同樣的問題,我想在Solr的複雜文檔的索引/存儲。我的方法是修改JsonLoader以接受以數組/對象爲值的複雜json文檔。

它存儲對象/數組,然後壓平它並索引字段。

例如基本示例文檔

{ 
     "titles_json":{"FR":"This is the FR title" , "EN":"This is the EN title"} , 
     "id": 1000003, 
     "guid": "3b2f2998-85ac-4a4e-8867-beb551c0b3c6" 
    } 

它將存儲

titles_json:{ 
       "FR":"This is the FR title" , 
       "EN":"This is the EN title" 
      } 

然後索引字段

titles.FR:"This是FR標題 「 titles.EN:」這是EN標題「

不僅你可以索引孩子文檔,而且當您在solr上執行搜索時,您將收到索引文檔的原始複雜結構。

如果你想與您現有的Solr檢查源代碼,安裝和集成的詳細信息,請

http://www.solrfromscratch.com/2014/08/20/embedded-documents-in-solr/

請注意,我已經測試這對Solr的4.9.0

M.

+0

您的解決方案與mongo連接器在當前版本中展平子文檔和數組的方式有什麼區別? – Ev0oD

+0

對不起,我從來沒有與mongo連接器工作,但我想它是扁平化JSON,然後將其發送到solr。在我的解決方案上,你做同樣的事情,但你也保留響應的json文檔的原始結構。此外,你可以從任何地方導入json數據,而不僅僅是mongo [我從db導入]。 – Michael