0

I have a Mongo DB database set up with the following collection, 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"
            },
        ....

I am trying to query by year to bring up the right element of the collection, and then query within the element's "runners" array based on input criteria. So far I have not been able to direct the query into this array. The goal is to derive members of an array of objects held within an element of a collection.

I looked at the syntax for mongo DB's $in and $all operators but I have not been able to construct a query that matches against the properties of the objects in the array.

I am using Node and this is the end-point I have tried to adapt;

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..........' ) );
});

The problem with this query is that it only returns the first array element that matches req.query, not all of the values that do.

Is there a concise way to construct a query into the objects of the array that returns all of the matches? Thank you for your time.

1
  • Either use aggregation or filter runners on application level. Commented Dec 4, 2017 at 16:47

2 Answers 2

1

This should get you started:

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);
});
Sign up to request clarification or add additional context in comments.

1 Comment

Excellent. Thank you very much.
0

Thank you Alex for the suggestion to try aggregation or the filters. I could not get the filter to work, based on what I read from the docs but I was able to get it working with this:

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..........' ) );
});

This works for a single search term, but if the requirement were runners who had more than one characteristic this would return runners with any of the characteristics, not the set of runners that has all of them. It seems that MongoDB should have something to make this less painful...

If anyone has any suggestions I would appreciate the help in refactoring. Thank you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.