如何知道mongodb查询有多少匹配

时间:2016-08-18 18:38:30

标签: node.js mongodb mongoose

在我的项目中,我有一个搜索栏,用户可以搜索其他用户。

我使用MongoDB作为我的数据库引擎,并在我的服务器的nod​​eJS上使用mongoose,到目前为止一切正常,除了一件事,我想按相关性排序结果。

想象一下,我有这个系列

{ 
    "nombre" : "Ramiro", 
    "apellido" : "Garcilazo", 
    "empresa" : "PEMEX", 
    "tamano" : "Grande(250+)", 
    "sector" : "Servicios", 
    "giro" : "Sustancias Químicas", 
    "actividad" : "Venta de petroquimicos", 
    "estado" : "Jalisco"
}
{ 
    "nombre" : "Luis", 
    "apellido" : "Alberto", 
    "empresa" : "GanaMex", 
    "tamano" : "Mediana (51-250)", 
    "sector" : "Construccion", 
    "giro" : "Agricultura, Ganaderia y Pesca", 
    "actividad" : "Graneros", 
    "estado" : "Aguascalientes"
}
{  
    "nombre" : "Ramon", 
    "apellido" : "Corona", 
    "empresa" : "CoronMex", 
    "tamano" : "Micro (1-10)", 
    "sector" : "Construccion", 
    "giro" : "Textiles, Prendas y Productos de Cuero", 
    "actividad" : "Venta de tiendas de campaña", 
    "estado" : "Ciudad de mexico"
}
{ 
    "nombre" : "Joe", 
    "apellido" : "Doe", 
    "empresa" : "Apple inc", 
    "tamano" : "Micro (1-10)", 
    "sector" : "Construccion", 
    "giro" : "Alimentos y Bebidas", 
    "actividad" : "Ejemplo", 
    "estado" : "Veracruz"
}
{ 
    "nombre" : "John", 
    "apellido" : "Smith", 
    "empresa" : "Google inc", 
    "tamano" : "Micro (1-10)", 
    "sector" : "Bienes", 
    "giro" : "Agricultura, Ganaderia y Pesca", 
    "actividad" : "XYZ", 
    "estado" : "Aguascalientes"
}
{ 
    "nombre" : "foo", 
    "apellido" : "bar", 
    "empresa" : "foobar inc.", 
    "tamano" : "Mediana (51-250)", 
    "sector" : "Servicios", 
    "giro" : "Alimentos y Bebidas", 
    "actividad" : "foo-bar", 
    "estado" : "Aguascalientes"
}
{ 
    "nombre" : "Jonathan", 
    "apellido" : "Ceja", 
    "empresa" : "It4Pymes", 
    "tamano" : "Grande(250+)", 
    "sector" : "Bienes", 
    "giro" : "Mineria, Petroleó y Gas", 
    "actividad" : "asdf", 
    "estado" : "Baja California"
}

我当前的查询看起来像这样

export function buscarProveedor(req, res) {
  var regTerms = [];
  //creates an RegExp array of all the terms the user searched
  var terms = req.body.term.split(" ");
  for (var i = 0; i < terms.length; i++) {
    regTerms.push(new RegExp(terms[i], 'i'));
  }
  //creates a single RegExp for all the term
  var regTerm = new RegExp(req.body.term, 'i');
  User.find({
      $and: [{
        //any of this that matches
        $or: [{
          nombre: regTerm
        }, {
          empresa: regTerm
        }, {
          sector: {
            $in: regTerms
          }
        }, {
          giro: {
            $in: regTerms
          }
        }, {
          estado: {
            $in: regTerms
          }
        }, {
          actividad: {
            $in: regTerms
          }
        }, {
          tags: {
            $in: regTerms
          }
        }]
      }, {
        //ignore this, just checks if is not another type of user
        empresa: {
          $exists: true
        }
      }, {
        //checks that doesn't gets the user that made the query
        _id: {
          $ne: req.body.id
        }
      }]
    }, '_id nombre empresa')
    .then(user => {
      //returns it to my front-end
      res.json(user).end();
    });
}

所以,例如在我的搜索栏中,我将&#34; Construccion&#34;,响应将是

{ 
    "_id": 0
    "nombre" : "Luis", 
    "empresa" : "GanaMex"
}
{  
    "_id": 1
    "nombre" : "Ramon", 
    "empresa" : "CoronMex", 
}
{ 
    "_id": 2
    "nombre" : "Joe", 
    "empresa" : "Apple inc", 
}

但是如果我把&#34; Construccion Textiles&#34;,即使id 1与2个术语相匹配,我也会得到相同的结果。

我想知道它有多少匹配,所以我可以通过相关性来订购它,把最多的匹配放在最上面。

我可以通过查询来实现,或者我必须在之后操作数据, 我真的不知道,我以前从未见过这个问题。

感谢。

编辑:好的,我使用$ match和$ group来做这件事,但仍然没有做我想要的,我用过它。

export function buscarProveedorAvansado(req, res) {
  var regTerms = [];
  var terms = req.body.term.split(" ");
  for (var i = 0; i < terms.length; i++) {
    regTerms.push(new RegExp(terms[i], 'i'));
  }
  var regTerm = new RegExp(req.body.term, 'i');

  User.aggregate([{
    $match: {
      $and: [{
        $or: [{
          nombre: regTerm
        }, {
          empresa: regTerm
        }, {
          sector: {$in: regTerms}
        }, {
          giro: {$in: regTerms}
        }, {
          estado: {$in: regTerms}
        }, {
          actividad: {$in: regTerms}
        }, {
          tags: {$in: regTerms}
        }]
      }, {
        empresa: {$exists: true}
      }, {
        _id: {
          $ne: req.body.id
        }
      }]
    }
  }, {
    $group: {
      "_id" : "$_id",
      "nombre" : {$max: "$nombre"},
      "empresa": {$max: "$empresa"},
      count: {
        $sum: 1
      }
    }
  }]).then(user => {
    console.log(user);
    res.json(user).end();
  });
}

我使用术语&#34; Construccion&#34;

得到这个结果
[{ 
    "_id": 0
    "nombre" : "Luis", 
    "empresa" : "GanaMex",
    "count": 1
}
{  
    "_id": 1
    "nombre" : "Ramon", 
    "empresa" : "CoronMex",
    "count": 1 
}
{ 
    "_id": 2
    "nombre" : "Joe", 
    "empresa" : "Apple inc", 
    "count": 1
}]

如果我使用术语&#34; Construccion Textiles&#34;

,我会得到完全相同的结果

我尝试了几件事,在$ sum上使用$ cond:

 $sum:[{
     $cond: {
         if: {
             nombre: regTerm
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             empresa: regTerm
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             sector: {
                 $in: regTerms
             }
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             giro: {
                 $in: regTerms
             }
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             giro: {
                 $in: regTerms
             }
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             estado: {
                 $in: regTerms
             }
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             nombre: regTerm
         },
         then: 1,
         else: 0
     }
 }, {
     $cond: {
         if: {
             nombre: regTerm
         },
         then: 1,
         else: 0
     }
 }]

获取mongo错误。

我认为$和$和$的问题是因为技术上最终是单一的,我不知道是否有解决方法。

我在这里错过了明显的吗?

1 个答案:

答案 0 :(得分:1)

您可以使用匹配功能,该功能会在您的查询撤回的所有文档中执行计数。

https://docs.mongodb.com/manual/reference/operator/aggregation/match/#perform-a-count