2014-09-19 75 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

相关问题