Поиск по дате в объекте в массиве - PullRequest
0 голосов
/ 16 мая 2018

У меня есть следующая схема Mongoose:

let ExerciserSchema = new Schema({
  username: {
    type: String,
    required: true
  },
  exercises: [{
    desc: String,
    duration: Number,
    date: {
      type: Date,
      default: new Date()
    }
  }]
});

Я хочу выполнить поиск по имени пользователя и ограничить результаты упражнения диапазоном дат.

Я пробовал эту функцию поиска:

let user = await Exerciser.find(
      { "username": name },
      { "exercises.date": { "$gte": from }},
      { "exercises.date": { "$lte": to }}
    ).exec((err, data) => {
      if (err) {
        res.json({ Error: "Data not found" })
        return done(err);
      }
      else {
        res.json(data);
        return done(null, data);
      }
    });

Однако он регистрирует ошибку и не возвращает данные. MongoError: Unsupported projection option: exercises.date: { $gte: new Date(1526342400000) }

Из этой ошибки я понимаю, что похоже, что моя дата ищется в миллисекундах, но я console.log прямо перед запуском вышеупомянутой функции, и она находится в режиме даты, что, как мне кажется, я хочу: 2018-05-01T00:00:00.000Z

Как я могу заставить эту работу работать так, чтобы я мог выполнять поиск по диапазону дат по моей схеме? Я могу изменить формат даты в схеме при необходимости. Я просто хотел бы самое простое решение. Спасибо за вашу помощь.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Мне удалось получить это. Этот ответ соответствует имени пользователя и фильтрует упражнения так, чтобы они находились между датами с именами переменных to и from. Это то, что я хотел.

    let user = Exerciser.aggregate([
    { $match: { "username": id }},
    { $project: { // $project passes along the documents with the requested fields to the next stage in the pipeline
      exercises: { $filter: {
        input: "$exercises",
        as: "exercise",
        cond: { $and: [
          { $lte: [ "$$exercise.date", to ] },
          { $gte: [ "$$exercise.date", from ] },
        ]}
      }},
      username: 1, // include username in returned data
      _id: 0
    }}
  ])

Результат:

[
  {
    "username": "scott",
    "exercises": [
      {
        "desc": "Situps",
        "duration": 5,
        "_id": "5af4790fd9a9c80c11aac696",
        "date": "2018-04-30T00:00:00.000Z"
      },
      {
        "desc": "Situps",
        "duration": 10,
        "_id": "5afb3f03e12e38020d059e67",
        "date": "2018-05-01T00:00:00.000Z"
      },
      {
        "desc": "Pushups",
        "duration": 8,
        "_id": "5afc08aa9259ed008e7e0895",
        "date": "2018-05-02T00:00:00.000Z"
      }
    ]
  }
]
0 голосов
/ 16 мая 2018

Ваш запрос неверен.Вы пытались написать условие AND, но вы разделили документы вместо того, чтобы объединить все в один.Это означает, что «второй» аргумент Model.find() был интерпретирован как «проекция полей», следовательно, ошибка:

MongoError: Неподдерживаемая опция проекции:

Так что это не «проблема схемы», а то, что вы отправили неверные аргументы в метод Model.find()

Также вам необходимо $elemMatchдля нескольких условий для элементов в массиве:

// Use a try..catch block with async/await of Promises
try {
  let user = await Exerciser.find({
    "username": name,
    "exercises": {
      "$elemMatch": { "date": { "$gte": from, "$lte": to } }
    }
  });
  // work with user
} catch(e) {
  // handle any errors
}

Самое главное, вы не await обратного вызова.Вы либо await Promise, как я здесь показываю, либо просто передаете callback вместо этого.Не то и другое.

Exerciser.find({
  "username": name,
  "exercises": {
    "$elemMatch": { "date": { "$gte": from, "$lte": to } }
  }
}).exec((err,user) => {
   // the rest
})

К вашему сведению, вы пытались сделать следующее:

Exerciser.find({
  "$and": [
    { "username": name },
    { "exercises.date": { "$gte": from }},
    { "exercises.date": { "$lte": to }}
  ]
)

Но на самом деле это все еще неправильно, поскольку без $elemMatch $gte и $lte применяются ко ВСЕМ элементам массива, а не только к одному.Таким образом, неверные результаты будут отображаться, если ЛЮБОЙ элемент массива будет меньше, чем дата, но не обязательно будет больше, чем.

Для элементов массива $elemMatch обеспечивает «между» двумя условиями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...