2015-08-31 203 views
1

我目前正在嘗試接受用戶輸入,以便用戶可以搜索數據庫。MongoDB搜索的用戶輸入

> db.test2.find().pretty() 
{ 
    "_id" : ObjectId("55de8a17f8389e208a1e7d7e"), 
    "name" : "john", 
    "favorites" : { 
     "vegetable" : "spinach", 
     "fruit" : "apple", 
    } 
} 
{ 
    "_id" : ObjectId("55de8a17f8389e208a1f6gg4"), 
    "name" : "becky", 
    "favorites" : { 
     "vegetable" : "spinach", 
     "fruit" : "apple", 
    } 
} 
{ 
    "_id" : ObjectId("55e3b6cbec2740181355b809"), 
    "name" : "liz", 
    "favorites" : { 
     "vegetable" : "spinach", 
     "fruit" : "banana", 
    } 
} 

在這個例子中,用戶將能夠搜索任何人喜歡的蔬菜,水果或他們最喜歡的蔬菜和喜愛的水果的組合。如果用戶輸入菠菜中最喜歡的蔬菜,所有三個將被退回。但是,如果用戶輸入最喜歡的蔬菜=菠菜和最喜歡的水果=蘋果,只有約翰和貝基將被退回。

在MongoDB中,您可以確定要搜索哪個參數。我試圖以一種方式編寫我的代碼,如果用戶將一個字段留空,它不應該被搜索。

我已經試過

$query = array("favorites.vegetable" => "$userInput", "favorites.fruit" => "$userInput2"); 

但如果兩個字段都留空,則不會返回任何結果。我想嘗試使用if語句:

if ($vegetable == NULL) 
{ 
    $query = array("favorites.fruit" => "$fruit"); 
} 

else if($fruit == NULL) 
{ 
    $query = array("favorites.vegetable" => "$vegetable"); 
} 

else 
{ 
    $query = array("favorites.vegetable" => "$vegetable", "favorites.fruit" => "$fruit"); 
} 

但如果我想使我的數據庫可以通過更多參數搜索,我會有太多的條件語句。有沒有什麼辦法讓我的Mongo搜索識別字段留空?

回答

0

問題的確是,「輸入來自哪裏?」。就好像你對輸入有某種結構,那麼編碼就很容易遵循一個模式。

正因爲如此,有兩個基本的變量,你可以清理的代碼基於什麼是變量簡單地contruct查詢:

$query = array(); 

if ($fruit != NULL) { 
    $query["favorites.fruit"] = $fruit; 
} 

if ($vegetable != NULL) { 
    $query["favorites.vegetable"] = $vegetable; 
) 

這意味着你要麼這裏$query要麼是結束空白以匹配所有內容或包含特定參數(一個或兩個),具體取決於內容是否爲空。

如果輸入有一定的結構,那麼你可以有很多更動態:

$input = array("fruit" => "apple", "vegetable" => "spinach"); 

$query = array(); 

foreach ($input as $key => $value) { 
    $query["favorites.$key"] = $value; 
} 

這是通過追加到$query但比單個變量更加動態的方式做同樣的事情。

另請注意,就MongoDB而言,您的文檔結構並不好。這大概真的應該是這樣的:

{ 
    "_id" : ObjectId("55de8a17f8389e208a1e7d7e"), 
    "name" : "john", 
    "favorites" : [ 
     { "type": "vegetable", "name": "spinach" }, 
     { "type": "fruit", "name": "apple" } 
    ] 
} 

雖然它最初可能看起來像查詢出來稍微複雜一些,刪除查詢中的「特定路徑」像「蔬菜」和「果」鍵有很多好處讓生活變得更容易,並且主要的「數據」可以被「索引」。鍵名不轉位的搜索,因此寬鬆的效率:

$input = array("fruit" => "apple", "vegetable" => "spinach"); 

$query = array(); 

foreach ($input as $key => $value) { 
    $query['$and'][] = array(
    'favorites' => array(
     '$elemMatch' => array(
      'type' => $key, 'name' => $value 
    ) 
    ) 
); 
} 

這是使用$elemMatch查找包含「所有的」數組元素,其中「兩」的「類型」和「名」的文件,一個漂亮的查詢輸入列表中的指定項目。

基本上看起來像這樣JSON:

{ 
    "$and": [ 
    { "favorites": { 
     "$elemMatch": { 
      "type": "fruit", "name": "apple" 
     } 
    }}, 
    { "favorites": { 
     "$elemMatch": { 
      "type": "vegetable", "name": "spinach" 
     } 
    }} 
    ] 
} 

這一切都歸結到知道如何操縱數據結構在您所選擇的語言,而「數據結構」都是MongoDB的查詢確實是,就你的語言是關心的。

對於結構的變化,然後condider是找人誰在他們的「最愛」,「蔬菜」現在變成了這樣:

{ "favorites.type": "vegetable" } 

這是自「favorites.type」好的可以被索引,而不是到:

{ "favorites.vegetable": { "$exists": true } } 

雖然這可以「技術上」使用索引,它並不真的這樣一個很好的方式。所以改變模式表示的方式是可取的,並提供更多的靈活性。

+0

非常感謝您的詳細解答!它真的幫助我。我會考慮如何構建我的數據庫。再次感謝你! – MongoNoob