MongoDB 3 стола дизайн, денормализованный, как тянуть и толкать - PullRequest
0 голосов
/ 09 ноября 2018

Добрый день, я сделал дизайн с тремя таблицами, я не уверен, что это правильно, но кажется, что он делает то, что мне нужно, и в основном это нормально. Я сделал денормализацию, потому что записи будут выполняться в одну таблицу один раз в месяц (отчеты), а в другую (TimeReports), как один раз или, может быть, пару раз в месяц, а чтение будет происходить каждый день.

Мне даже нужна денормализация, или, возможно, ссылки ObjectId помогут? Я могу выполнять поиск, как я делаю по отчетам, я могу найти отдельные TimeReports и все TimeReports конкретным пользователем, так что, может быть, здесь не нужна денормализация? Но мне нужно иметь некоторые указания на TimeReports в отчетах.

поэтому у меня есть это:

let TimeReportSchema = new Schema({
  hours: Number,
  rate: Number,
  sum: Number,
  companyId: {type: mongoose.Schema.Types.ObjectId, ref: 'Company'},
  companyName: String,
  userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
  reportId: {type: mongoose.Schema.Types.ObjectId, ref: 'Report'},
  date: {type: Date, default: Date.now},
  updated: {type: Boolean, default: false}
})

let ReportSchema = new Schema({
  userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
  director: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
  invoice: {type: String, default: ""},

  time_reports: [TimeReportSchema],

  summary: {type: Number, default: 0},
  date: {
    type: Date,
    default: Date.now
  }
})

var UserSchema = new Schema({
    name: {
        type: String,
        required: true
    },
    email: {
        type: String,
        unique: true,
        required: true
    },
    ...

    reports: [ReporSchema],

    companyId: {type: mongoose.Schema.Types.ObjectId, ref: 'Company'},
    positionId: {type: mongoose.Schema.Types.ObjectId, ref: 'Position'},
});

Раз в месяц я создаю отчет и добавляю в него каждого пользователя, затем пользователь создает TimeReports, а они также отправляют в User.reports и Report (отчет за этот месяц).

Как мне удалить TimeReport из User.reports? Если я могу исключить отчеты из схемы пользователя, у меня все еще есть проблема с управлением обновлениями и удалением TimeReports из отчетов.

app.delete('/time-report/:id', async (req, res) => {
  let userId;
  await TimeReport.findById(req.params.id, (error, report) => {
    checkForError(res, error);
    userId = report.userId;
    console.log(report, 'report1');
  })
  await TimeReport.remove({
    _id: req.params.id
  }, (error, report) => { 
    checkForError(res, error)
  })
  // User.update({_id: userId}, 
  // {$pull: {'reports.time_reports': {_id: req.params.id}}})
  // res.send({
  //     success: true
  // })
  // that didn't worked
})

app.get('/time-report/:id', (req, res) => {
  let id = req.params.id
  TimeReport.findById(id, (err, reports) => {
    res.send(reports)
  })
})

app.get('/time-reports/:userId', (req, res) => {
  TimeReport.find({userId: req.params.userId}, (err, reports) => {
    console.log(reports, 'reports')
    res.send(reports)
  }).sort({date:-1})
})

app.post('/time-report/:id', async (req, res) => {
  var begin = moment().startOf('month')
  var end = moment(begin).endOf('month')
  let query = {
    userId: req.params.id,
    date: {
      $gte: begin.toDate(),
      $lt: end.toDate()
    }
  }
  let hours = Number(req.body.hours)
  let rate = Number(req.body.rate)
  let sum = hours * rate
  await Report.findOne(query, async (error, report) => {
    console.log(report, 'report for id')
    let reportId = report._id
    newTimeReport = new TimeReport({
      hours, rate, sum, companyId, company, userId, reportId
    })
    newTimeReport.save((error) => {
      checkForError(res, error)
      report.time_reports.push(newTimeReport)
      report.summary += sum
      report.save((error) => {
        checkForError(res, error)
      })
    })
  })

User.findById(req.params.id, (err, user) => {
    user.reports.forEach((report, index) => {
      if(report.date.getMonth() === begin.toDate().getMonth()) {
        report.summary += sum
        report.time_reports.push(newTimeReport)
      }
    })
    user.save((error) => {
      checkForError(res, error)
    })
    res.send(user)
  })

метод сложнее и выглядит ужасно.

app.put('/time-report/:id', async (req, res) => {
  let id = req.params.id;
  let reportId;
  let oldSum;
  let newSum;
  TimeReport.findById(id, async (err, report) => {
    reportId = report.reportId
    oldSum = report.sum
    report.hours = Number(req.body.hours)
    report.rate = Number(req.body.rate)
    report.company = req.body.companyName
    report.companyId = req.body.companyId
    report.sum = Number(req.body.hours) * Number(req.body.rate)
    report.updated = true
    report.save((error) => {
    })
    Report.findById(reportId, (error, report) => {
      report.summary -= oldSum
      report.summary += newSum
      for(let j = 0; j < report.time_reports.length; j++) {
        if(report.time_reports[j]._id == id) {
          report.time_reports[j].hours = Number(req.body.hours)
          report.time_reports[j].rate = Number(req.body.rate)
          report.time_reports[j].sum = newSum
        }
      }
      report.save((error) => {
      })
    })
    User.findById(report.userId, (err, user) => {
      loop1:
      for(let i = 0; i < user.reports.length; i++) {
        loop2:
        for(let j = 0; j < user.reports[i].time_reports.length; j++) {
          if(user.reports[i].time_reports[j]._id == id) {
            user.reports[i].summary -= oldSum
            newSum = Number(req.body.hours) * Number(req.body.rate)
            user.reports[i].summary += newSum
            user.reports[i].time_reports[j].hours = Number(req.body.hours)
            user.reports[i].time_reports[j].rate = Number(req.body.rate)
            user.reports[i].time_reports[j].sum = newSum
            user.reports[i].time_reports[j].company = req.body.companyName
            user.reports[i].time_reports[j].companyId = req.body.companyId
            user.reports[i].time_reports[j].updated = true
            break loop1;
          }
        }
      }
      user.save((error) => {
      })
    })
    res.send(report)
  })
})

Не могли бы вы дать мне совет по поводу хорошего дизайна?

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