1

This is a two part mongoDB/mongoose question

I want to concat a First Name/Last Name into "name" AND I only want to show the single "current" item from an array.

So if my data looks like this

[{
    "fname":"bob",
    "lname":"jones",
    "role":"professional", 
    "active":true,
    "jobs":[{
        "job":"janitor",
        "current":true
    },{
        "job":"dog groomer"
        "current":false
    }]
},{
    "fname":"sally",
    "lname":"peterson",
    "role":"professional", 
    "active":true,
    "jobs":[{
        "job":"engineer",
        "current":false
    },{
        "job":"college admin"
        "current":true
    }]
},{
    "fname":"jackson",
    "lname":"smiley",
    "role":"professional", 
    "active":true,
    "jobs":[{
        "job":"car salesman",
        "current":false
    },{
        "job":"street sweeper"
        "current":false
    }{
        "job":"house painter"
        "current":true
    }]
},{
    "fname":"katie",
    "lname":"smiley",
    "role":"amature", 
    "active":true,
    "jobs":[{
        "job":"drone entheuast",
        "current":true
    }]
}]

And I want my return data to be

[{
    name:"bob jones", 
    job:"janitor"
},{
    name:"sally peterson", 
    job:"college admin"},
{
    name:"jackson smiley", 
    job:"house painter"
}]

Currently - I am using this mongoose syntax - but it's not enough...

module.exports.getActiveList = function( callback ) {
        const query = { "role":"professional", "active":true }
        People.find( query, 'name job', callback );
    }

How would I do that?

1 Answer 1

1

You can try below aggregation

You can use $concat to combine both fname and lname as a name and $filter to obtain current active job from the jobs array

People.aggregate([
  { "$match": { "role": "professional", "active": true }},
  { "$project": {
    "name": { "$concat": ["$fname", " ", "$lname"] },
    "jobs": {
      "$filter": {
        "input": "$jobs",
        "as": "job",
        "cond": { "$eq": ["$$job.current", true] }
      }
    }
  }},
  { "$project": { "name": 1, "job": { "$arrayElemAt": ["$jobs.job", 0] }}}
])

Or using $let to complete in a single stage

People.aggregate([
  { "$match": { "role": "professional", "active": true }},
  { "$project": {
    "name": { "$concat": ["$fname", " ", "$lname"] },
    "job": {
      "$let": {
        "vars": {
          "jobs": {
            "$filter": {
              "input": "$jobs",
              "as": "job",
              "cond": { "$eq": ["$$job.current", true] }
            }
          }
        },
        "in": { "$arrayElemAt": ["$$jobs.job", 0] }
      }
    }
  }}
])
Sign up to request clarification or add additional context in comments.

8 Comments

Anthony, thank you for your time. I've modified my question a bit, because I don't know how the aggregation syntax fits in with the query filter syntax..see above question modifications
I am trying your suggestions now
ok great... I have updated the answer according to your question
hum - I get this error - MongoError: The 'cursor' option is required, except for aggregate with the explain argument -- also can you explain what "$arrayElemAt": ["$$jobs.job", 0] is doing...
Here is your first answer stackoverflow.com/questions/50101104/…... and the $arrayElemAt takes the indexed element from the array (the second argument is for index)
|

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.