2016-09-27 59 views
0

編輯 這是在我的應用程序的心臟,因此,我提出了一個bounty整蠱MongoDB的搜索challange - 賞金

原始

我有,我從來沒有遇到一個棘手的mongoDB問題。我的網路研究不成功。

文件:

documentscollection有一個搜索object含有名爲keys和陣列values。密鑰以八個categorys之一命名,相應的值爲array,其中包含該類別的items

{ 
    _id: "bRtjhGNQ3eNqTiKWa", 
    /* */ 
    search :{ 
    usage: ["accounting"], 
    test: ["knowledgetest", "feedback"] 
    }, 
    test: { 
    type:"list", 
    vals: [ 
    {name:'knowledgetest', showName: 'Wissenstest'}, 
    {name:'feedback', showName: '360 Feedback'}, 
    ] 
    }, 
    usage: { 
    type:"list", 
    vals: [ 
    {name:'accounting', showName: 'Accounting'},  
    ] 
    } 
}, 
{ 
    _id: "7bgvegeKZNXkKzuXs", 
    /* */ 
    search :{ 
    usage: ["recruiting"], 
    test: ["intelligence", "feedback"] 
    }, 
    test: { 
    type:"list", 
    vals: [ 
    {name:'intelligence', showName: 'Intelligenztest'}, 
    {name:'feedback', showName: '360 Feedback'}, 
    ] 
    }, 
    usage: { 
    type:"list", 
    vals: [ 
    {name:'recruiting', showName: 'Recruiting'},  
    ] 
    } 
}, 

查詢

query的是含有相同category - keysarray - values一個object

{ 
    usage: ["accounting", "assessment"], 
    test : ["feedback"] 
} 

期望得到的結果

  • 如果查詢是空的,我想all文件。
  • 如果查詢有one類別和任意數量的項目,我希望所有documents具有指定的category中的所有items
  • 如果查詢有多個類別,我希望所有documents在所有指定的categorys中都具有所有items

我嘗試次數

我試過各種變化:

XX.find({ 
'search': { 
    "$elemMatch": { 
    'tool': { 
     "$in" : ['feedback'] 
    } 
    } 
} 

沒有成功。 編輯 試過:'search.test': {$all: (query.test ? query.test : [])}如果我沒有選擇任何東西,它會給我沒有結果;當我只看test類別時,右邊documents;當我另外看usage類別時什麼也沒有。

+0

當查詢中給定的所有數組元素搜索,你將不得不使用$所有,而不是$ elemMatch。儘管如此,這並不能解決您的問題,基本上,您存儲的數據結構不適合您想要創建的查詢。您應該使用類別作爲密鑰來單獨存儲陣列。然後,每個單獨的查詢歸結爲{'category':{$ all:[myinputarray]}}。請注意,這是一個文檔數據庫 - 建模將由您期望的QUERIES完成,而不是您想象得最好的任何模型。 – mtj

+0

@mtj每個文檔還包含類別作爲鍵,但是數據嵌套在'showName:「字符串中,類型:{},vals:[{name:」string「,showName:」string「}],[ {...}]'與相關條目相關的參數是'vals [x] .name'。 –

+0

@mtj我編輯了我的問題**文檔**部分。 –

回答

1
let tools = [] 
    const search = {} 
    for (var q in query) { 
     if (query.hasOwnProperty(q)) { 
     if (query[q]) { 
      search['search.'+q] = {$all: query[q] } 
     } 
     } 
    } 


    if (Object.keys(query).length > 0) { 
     tools = ToolsCollection.find(search).fetch() 
    } else { 
     tools = ToolsCollection.find({}).fetch() 
    } 

就像一個魅力

0

我在評論中已經暗示過:您的文檔結構不支持高效且簡單的搜索。我只能猜測原因,但我懷疑你堅持一些像「模式」或「規範化」這樣的關係性思想,這對於文檔數據庫是沒有意義的。

沒有更深的挖掘模型的問題,我能想象這樣的事情對你的情況:

{ 
    _id: "bRtjhGNQ3eNqTiKWa", 
    /* */ 
    search :{ 
    usage: ["accounting"], 
    test: ["knowledgetest", "feedback"] 
    }, 
    test: { 
    "knowledgetest" : { 
     "showName": "Wissenstest" 
    }, 
    "feedback" : { 
     "showName": "360 Feedback" 
    } 
    }, 
    usage: { 
    "accounting" : { 
     "values" : [ "knowledgetest", "feedback" ], 
     "showName" : "Accounting" 
    } 
    } 
}, 
{ 
    _id: "7bgvegeKZNXkKzuXs", 
    /* */ 
    search : { 
    usage: ["recruiting"], 
    test: ["intelligence", "feedback"] 
    }, 
    test: { 
    "intelligence" : { 
     showName: 'Intelligenztest' 
    }, 
    "feedback" : { 
     showName: '360 Feedback' 
    } 
    }, 
    usage: { 
    "recruiting" : { 
     "values" : [ "intelligence", "feedback" ], 
     "showName" : "Recruiting" 
    } 
    } 
} 

然後,在「會計」,「knowledgetest」和「反饋」是一個簡單的搜索

{ "usage.accounting.values" : { $all : [ "knowledgetest", "feedback"] } } 

其可以很容易地在一個和條件可使用多次:

{ 
    { "usage.accounting.values" : { $all : [ "knowledgetest", "feedback"] } }, 
    { "usage.anothercategory.values" : { $all [ "knowledgetest", "assessment" ] } } 
} 

即使是零次大小寫也符合您的搜索要求,因爲沒有任何這些條件的and-filter會生成{find}所有過濾器表達式。

再一次,要說清楚:使用mongo時,忘記所有內容你知道這是關係世界的「最佳實踐」。您需要考慮的是:您的查詢是什麼,以及我的文檔模型如何以理想的方式支持這些查詢。

+0

非常感謝。我會盡力實現這一點。它可能需要一些時間,但如果它的工作,我已經提出了[賞金](https://bountify.co/mongodb-complex-query-design-2):) 我有接近沒有經驗的查詢設計,所以你可以給的所有額外的幫助是值得歡迎的。這是賞金的原因! –

+0

基本上它很簡單:設計你的應用程序並問自己:我需要從數據庫中查詢哪個地方需要查詢什麼。然後,編寫文檔,以便這些查詢儘可能簡單高效。不要害怕冗餘,不要害怕反規範化。除非您在文檔中存儲真正的大事物,否則最大文檔大小爲16MB是充足的,現在磁盤存儲成本幾乎沒有。 (當然,最後一句話是用一粒鹽;-)) – mtj

+0

我能夠使用我已有的數據結構。剛發佈了一個答案 –