MongoDB:查询嵌套在集合属性中的对象数组的元素

时间:2017-12-04 16:23:59

标签: arrays node.js mongodb

我使用以下集合设置Mongo DB数据库:Races:

[
    {
        "_id": "5a24b47f8b8498252a0a0ef9",
        "year": 2017,
        "runners": [
            {
                "Place": "1",
                "Div/Tot": "1/126",
                "FName": "XXXX",
                "LName": "XXXX",
                "Num": "XXXX",
                "S": "M",
                "Ag": "25",
                "City": "XXXX",
                "St": "XX",
                "Gun-Time": "32:15.2",
                "Net-Time": "32:14.91",
                "Pace": "5:13"
            },
            {
                "Place": "2",
                "Div/Tot": "1/138",
                "FName": "XXXX",
                "LName": "XXXX",
                "Num": "XXXX",
                "S": "M",
                "Ag": "34",
                "City": "XXXX",
                "St": "XXXX",
                "Gun-Time": "MD",
                "Net-Time": "32:19.0",
                "Pace": "32:18.78"
            },
        ....

我试图按年查询以显示集合的正确元素,然后根据输入条件在元素的“runners”数组中查询。到目前为止,我还没有能够将查询指向此数组。目标是派生保持在集合元素内的对象数组的成员。

我查看了mongo DB的$in$all运算符的语法,但是我无法构造一个与数组中对象属性匹配的查询。

我正在使用Node,这是我试图适应的终点;

router.route( '/race/:year' )
  .get( ( req, res ) => {
      console.log( 'query', req.query, ' params ', req.params ); 
      Race.find( { year: req.params.year }, {runners: {$elemMatch: req.query } } )  
      .then( race => {
          return res.json( race );
      } )
      .catch( () => res.status( 500 ).send( 'endpoint error..........' ) );
});

此查询的问题在于它只返回匹配req.query的第一个数组元素,而不是所有值。

是否有一种简洁的方法来构造一个返回所有匹配的数组对象的查询?感谢您的时间。

2 个答案:

答案 0 :(得分:1)

这应该让你开始:

Race.aggregate([
{ 
    $match: {
        "year": req.params.year // filter out all documents that we're not interested in
    }
}, {
    $project: {
        _id: 0
        "runners": {
            $filter: {
                input: "$runners", // we want to filter the "runners" array
                as: "runner",
                cond: {
                    $eq: [ "$$runner.Ag", "34" ] // just an example filter
                }
            }
        }
    }
}], function(err, results) {
      rs.json(results);
});

答案 1 :(得分:0)

感谢Alex提供尝试聚合或过滤器的建议。根据我从docs读到的内容,我无法使过滤器工作,但我能够使用它:

router.route( '/race/:year' )
  .get( ( req, res ) => {
      console.log( 'query', req.query, ' params ', req.params ); 

      Race.find( { year: req.params.year } )
     .then( race => {
        let results = [];
        const runners = race[ 0 ].runners;
        const searchObj = req.query;
        const searchKeys = Object.keys( searchObj );

        for ( let i = 0; i < runners.length; i++ ){
            searchKeys.forEach( function( searchTerm ){ 
                if ( runners[ i ][ `${ searchTerm }` ] === searchObj[ `${ searchTerm }` ] ){
                    results.push( runners[ i ] );
                }
            }
        ) } 
        return res.json( results );
      })
      .catch( () => res.status( 500 ).send( 'endpoint error..........' ) );
});

这适用于单个搜索词,但如果要求是具有多个特征的跑步者,则这将返回具有任何特征的跑步者,而不是具有所有特征的跑步者集合。似乎MongoDB应该有一些东西可以减少痛苦......

如果有人有任何建议,我将非常感谢重构方面的帮助。谢谢。