2014-09-19 47 views
0

我有一個搜索欄,這樣當用戶按下回車鍵後,搜索欄中的字符串就會發送到我的ExpressJS服務器。然後,服務器需要查看MongoDB中的每個文檔;如果其任何字段與搜索欄中的內容匹配,則會找到文檔。如何分別搜索每個文檔字段的特定值?

我目前的代碼在技術上可行,但它看起來非常冗餘,可能效率很低。我在每個字段上使用find()方法,將匹配保存在數組中。在單獨搜索每個字段後,我修剪找到的匹配數組,刪除任何重複項。

有沒有更好的方法來做到這一點?請參閱下面我當前的代碼:

router.get('/', function(req, res) { 
    var regSearch = new RegExp('.*'+searchdata+'.*', 'i'); //Create regular expression of search data -> (text in search bar) 
    var arr = []; 


    InventoryObject.find({productId: {$regex: regSearch}}).limit(100).exec(function (err, data) { //Get all docs with a matching productId 
     InventoryObject.find({scannerIn: {$regex: regSearch}}).limit(100).exec(function (err, data1) { //Get all docs with a matching scannerIn 
     InventoryObject.find({scannerOut: {$regex: regSearch}}).limit(100).exec(function (err, data2) { //Get all docs with a matching scannerOut.... 
      InventoryObject.find({dateIn: {$regex: regSearch}}).limit(100).exec(function (err, data3) { 
      InventoryObject.find({dateOut: {$regex: regSearch}}).limit(100).exec(function (err, data4) { 
       InventoryObject.find({productName: {$regex: regSearch}}).limit(100).exec(function (err, data5) { 
       InventoryObject.find({purchaseOrder: {$regex: regSearch}}).limit(100).exec(function (err, data6) { 
        InventoryObject.find({productDestination: {$regex: regSearch}}).limit(100).exec(function (err, data7) { 

        InventoryObject.find({productCost: parseFloat(searchdata)}).limit(100).exec(function (err, data8) { 

         //Concatenate all matched documents into single array 
         arr = arr.concat(data, data1, data2, data3, data4, data5, data6, data7, data8); 

         //Remove undefined last element... 
         arr.splice(arr.length-1, 1); 

         //Iterate through array and remove any documents that are duplicates 
         for (var i = 0; i < arr.length; i++) { 
         for (var j = i+1; j < arr.length; j++) { 
          if (arr[i]._id.toString() === arr[j]._id.toString()) { 
          arr.splice(j, 1); 
          j--; 
          } 
         } 
         } 

         //Sort the documents by their _id property 
         arr.sort(function (a, b) { 
         if (a._id < b._id) return +1; 
         if (a._id > b._id) return -1; 
         return 0; 
         }); 

         //If the array is longer than 100, truncate it. 
         if (arr.length > 100) 
         arr.length = 100; //truncate to 100 elements sorted by the order they were inputted 

         //console.log(arr); 

         res.render('index', {'inventoryObjects': arr}); 
         searchdata = ''; //Clear search data  
        });  
        });  
       });  
       });  
      });  
      });  
     });  
     }); 
    }); 
    }); 

這裏是我的模式可供參考:

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 
var InventoryObject = new Schema({ 
    productId: String, 
    scannerIn: String, 
    scannerOut: String, 
    dateIn: String, 
    dateOut: String, 
    productName: String, 
    purchaseOrder: String, 
    productDestination: String, 
    productCost: Number 
}); 
mongoose.model('InventoryObject', InventoryObject); 
+0

你有沒有看創建一個[文本索引](http://docs.mongodb.org/manual/core/index-text/),其中包含您想要搜索的所有列,然後使用'$ text'查詢? – JohnnyHK 2014-09-19 17:02:51

回答

0

不幸的是這是不可能在目前的蒙戈DB版本。

你應該優化您的查詢是這樣的:

InventoryObject.find({ 
    $or:[ 
     {productId: {$regex: regSearch}}, 
     {scannerIn: {$regex: regSearch}}, 
     ... 
    ] 
}); 

但如果你真的需要優化這些查詢的速度,你應該將模式更改爲類似:

{ 
    attributes: [ 
     {key: 'productId', value: 'product ID'}, 
     {key: 'scannerId', value: 'scanner ID'}, 
     ... 
    ] 
} 
+0

非常感謝!明確的迴應。我使用了你提出的第一個優化,因爲我有點緊張。它的工作方式比我的原始代碼更好,它更簡潔!謝謝! – davidcox 2014-09-19 17:17:13

相關問題