简体   繁体   中英

Returning part of the array inside MongoDB Collection

I have a users collection:

{
  "_id": "5fb3f05fa664961df03e2b7a",
  "username": "testy",
  "count": 3,
  "exercises": [
  {
    "description": "test1",
    "duration": "1",
    "date": "2020-01-01T00:00:00.000Z"
  },
  {
    "description": "test2",
    "duration": "10",
    "date": "2020-02-01T00:00:00.000Z"
  },
  {
    "description": "test3",
    "duration": "100",
    "date": "2020-03-01T00:00:00.000Z"
  }
 ]
}

I want to partially return some of the exercises that match my queries. Two of these queries are date range:

&from=2020-01&to=2020-02

I come across $elemMatch , but I can't get the result I want. It just returns the whole exercises array. This is how I tried to use it:

const from = req.query.from
let query = {}
query._id = userId
if (from) {
  query.exercises = { $elemMatch: { date: { $gte: new Date(from) } } }
}

And this is how I create my exercises array:

$push: {
    exercises: {
      description,
      duration,
      date: new Date(date || getCurrentStringDate())
    },

What I want eventually is such a result:

{
  "_id": "5fb3f05fa664961df03e2b7a",
  "username": "testy",
  "count": 3,
  "exercises": [
  {
    "description": "test1",
    "duration": "1",
    "date": "2020-01-01T00:00:00.000Z"
  },
  {
    "description": "test2",
    "duration": "10",
    "date": "2020-02-01T00:00:00.000Z"
  },
 ]
}

when these queries are given in the URL:

&from=2020-01&to=2020-02

Am I using the $elemMatch wrong? Or it isn't the solution for this case at all?

I was wrong about using $elemMatch . It wasn't a solution for my case. Eventually I ended up using this pipeline for Collection.aggregate and used $project to create a new filtered array(via $filter and $cond ):

let dateRange = []
  if (from) {
    dateRange.push({$gte: [ "$$item.date", from]})
  }
  if (to) {
    dateRange.push({$lte: [ "$$item.date", to]})
  }
  if (dateRange.length !== 0) {
    pipeline.push({
      $project: {
        log: {
          $filter: {
            input: "$log",
            as: "item",
            cond: { $and: dateRange }
          }
        }
      }
    })
  }

Most probably it's not the best solution but worked for my problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM