如何单独搜索每个文档字段以获取特定值?

时间:2014-09-19 15:49:51

标签: regex node.js mongodb express mongoose

我有一个搜索栏,这样当用户按下回车键时,搜索栏中的字符串就会发送到我的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);

1 个答案:

答案 0 :(得分:1)

不幸的是,在当前的Mongo DB版本中这是不可能的。

您应该像这样优化您的查询:

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

但是,如果您确实需要优化此类查询的速度,则应将架构更改为:

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