首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用快递4和猫鼬路由到子文档

用快递4和猫鼬路由到子文档
EN

Stack Overflow用户
提问于 2017-10-20 00:07:25
回答 2查看 935关注 0票数 0

编辑:,有可能问题是由于修改引起的。我当前的查询如下:

代码语言:javascript
复制
router.route('/projects/:project_id/techDetails')
  .get(function(req, res) {
    Project.findById(req.params.project_Id, function(err, project) {
        if (err)
            return res.send(err);
        res.json(project);
        console.log('get success (project techDetails)');
    });
});

这将返回null。尽管它在各个方面都与工作代码行相同,但在路由中添加了‘/techDetails’。

原始问题:

我正在用速递和蒙戈构建一个普通的堆栈应用程序。我不知道如何正确地路由到嵌套的文档。

这是我的项目模式

代码语言:javascript
复制
const ProjectSchema = new Schema({
  idnumber: { type: Number, required: true },
  customername: String,
  projectdetails: String,
  jobaddress: String,
  techDetails: [{
    scope: String,
    edgedetail: String,
    lamination: String,
    stonecolour: String,
    slabnumber: String,
    slabsupplier: String,
    purchaseordernum: String,
    splashbacks: String,
    apron: String,
    hotplate: String,
    sink: String,
    sinkdetails: String,
    tappos: String
  }],
  sitecontactname: String,
  sitecontactnum: String,
  specialreq: String,
  install_date: String,
  created_on: { type: Date, default: Date.now },
  created_by: { type: String, default: 'SYSTEM' },
  active: { type: Boolean, default: true },
  flagged: { type: Boolean, default: false },
});

我可以使用GETPOST成功地路由到/projects/:project_id,用GETPUTDEL成功地路由到/projects/:project_id

使用PUT路由和项目的_ID,我可以将新条目推送到项目的techDetails子文档数组。生成的JSON数据如下所示:

代码语言:javascript
复制
{
"_id": "59e577e011a3f512b482ef13",
"idnumber": 52,
"install_date": "10/20/2017",
"specialreq": "some...",
"sitecontactnum": "987654321",
"sitecontactname": "bill",
"jobaddress": "123 st",
"projectdetails": "some stuff",
"customername": "B Builders",
"__v": 16,
"flagged": false,
"active": true,
"created_by": "SYSTEM",
"created_on": "2017-10-17T03:24:16.423Z",
"techDetails": [
    {
        "scope": "Howitzer",
        "edgedetail": "12mm",
        "lamination": "No",
        "stonecolour": "Urban™",
        "slabnumber": "1",
        "slabsupplier": "Caesarstone",
        "purchaseordernum": "no",
        "splashbacks": "No",
        "apron": "No",
        "hotplate": "N/A",
        "sink": "N/A",
        "sinkdetails": "no",
        "tappos": "no",
        "_id": "59e577e011a3f512b482ef14"
    },
    {
        "scope": "kitchen",
        "edgedetail": "12mm",
        "lamination": "etc",
        "_id": "59e7da445d9d7e109c18f38b"
    },
    {
        "scope": "Vanity",
        "edgedetail": "12mm",
        "lamination": "No",
        "stonecolour": "Linen™",
        "slabnumber": "1",
        "slabsupplier": "Caesarstone",
        "purchaseordernum": "1",
        "splashbacks": "No",
        "apron": "No",
        "hotplate": "N/A",
        "sink": "N/A",
        "sinkdetails": "no",
        "tappos": "woo",
        "_id": "59e81e3324fb750fb46f8248"
    }//, more entries omitted for brevity
  ]
}

正如你所看到的,到目前为止,一切都如期而至。但是,现在我需要编辑和删除这个techDetails数组中的各个条目。我还想直接使用projects/:project_id/techDetailsprojects/:project_id/techDetails/:techdetails_id路由到它们。

据我所见,有两种方法可以解决这个问题。要么我可以:

( A)为使用techDetails的mergeParams使用新的路由文件。这是我目前正在尝试的方法,但是我不知道如何完成.find来返回所有的techDetails,因为我只能使用Project模型模式,并且我不确定如何访问子文档。

摘录自我的routes.js

代码语言:javascript
复制
const techDetails = require('./techDetails');
//other routes here

//see techdetails file
router.use('/projects/:project_id/techdetails', techDetails);

//here lies an earlier, failed attempt
/* router.route('/projects/:project_id/techdetails/:techDetails_id')
.get(function(req, res) {
    Project.findById(req.params.project_id.techDetails_id, function(err, 
project) {
        if (err)
            return res.send(err);
        res.json(project.techDetails);
        console.log('get success (techDetails)');
    });
  })
; */

还有我的techdetails.js

代码语言:javascript
复制
const express = require('express');
const Project = require('./models/project');
const router = express.Router({mergeParams: true});

router.get('/', function (req, res, next) {
/*  Project.find(function(err, techDetails) {
    if (err)
        return res.send(err);
    res.json(techDetails);
    console.log('get success (all items)');
  }); */
  res.send('itemroutes ' + req.params);
})

router.get('/:techDetails_id', function (req, res, next) {
  res.send('itemroutes ' + req.params._id)
})

module.exports = router

我可以成功地检查路线是否与邮差一起工作,两者都会收到回复。现在的问题是,我不想使用res.send,而是使用res.jsonProject.find (或类似的)来获得techDetails

然而,还有另一种选择:

B)将techDetails文档放入它自己的模式中,然后在项目中填充一个ID数组。

然而,这似乎更复杂,所以如果可以的话,我宁愿避免这样做。

欢迎您提出任何想法和建议。如果需要更多的代码,请告诉我。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-01 03:40:39

所以,我找到的解决方案是A)和B的组合。我使用了一个单独的路由文件并将({mergeParams: true})放在路由器声明中,并且为techDetails嵌套模型创建了一个单独的文件,而没有声明它。但是我不相信这两件事都没有任何意义.但不管怎样。

在我的路由中,我得到的工作代码是:

代码语言:javascript
复制
router.use('/projects/:project_id/techDetails', TechDetails);

techDetails.js:

代码语言:javascript
复制
const router = express.Router({mergeParams: true});

router.route('/')
  .get(function(req, res) {
    Project.findById(req.params.project_id,
      'techDetails', function(err, project) {
        if (err)
            return res.send(err);
        res.json(project);
        console.log('get success (project techDetails)');
    });
});

有什么不同吗?即,'techDetails',行中的Project.findById参数。根据猫鼬API,它充当select语句。唯一的主要区别是我修正了我的原始代码中的一个错误( project_idproject_Id编写的)。可疑的..。)。如果我使用VS或其他什么来代替notepad++,我可能会注意到这一点,但这是我最喜欢的编码领域。

返回res.json(project.techDetails)并删除'techDetails', select参数可能是可能的,但我可能不会测试这个参数。

编辑:最终将techDetails迁移到一个单独的文件中,这意味着它们不再使用objectId生成,这对于PUT和DEL至关重要。我可能在数组声明中使用了一对简单的大括号,但直到我将它重新迁移回项目模式之后,我才想到这一点.

票数 0
EN

Stack Overflow用户

发布于 2017-10-20 00:56:11

在这种情况下,我会将techDetails放在一个单独的模式中:

代码语言:javascript
复制
const ProjectSchema = new Schema({
  idnumber: { type: Number, required: true },
  customername: String,
  projectdetails: String,
  jobaddress: String,
  techDetails: [techDetailsSchema],
  sitecontactname: String,
  sitecontactnum: String,
  specialreq: String,
  install_date: String,
  created_on: { type: Date, default: Date.now },
  created_by: { type: String, default: 'SYSTEM' },
  active: { type: Boolean, default: true },
  flagged: { type: Boolean, default: false },
});

不要将techDetails模式注册到mongoose.model,因为它是一个子文档。将它放在一个单独的文件中,并在项目模型文件(const techDetailsSchema = require('./techDetails.model');)中要求它。

我将创建如下控制器函数:

GET (all):

代码语言:javascript
复制
module.exports.techDetailsGetAll = function (req, res) {   
  const projectId = req.params.projectId;

  Project
    .findById(projectId)
    .select('techDetails')
    .exec(function (err, project) {
      let response = { };

      if (err) {
        response = responseDueToError(err);
      } else if (!project) {
        response = responseDueToNotFound();
      } else {
        response.status = HttpStatus.OK;
        response.message = project.techDetails;
      }

      res.status(response.status).json(response.message);
    });
}

获得GET (1):

代码语言:javascript
复制
module.exports.techDetailsGetOne = function (req, res) {
  const projectId = req.params.projectId;
  const techDetailId = req.params.techDetailId;

  Project
    .findById(projectId)
    .select('techDetails')
    .exec(function (err, project) {
      let response = { };

      if (err) {
        response = responseDueToError(err);
      } else if (!project) {
        response = responseDueToNotFound();
      } else {
        let techDetails = project.techDetails.id(techDetailId);

        if (techDetails === null) {
          response = responseDueToNotFound();
        } else {
          response.status = HttpStatus.OK;
          response.message = techDetails;
        }
      }

      res.status(response.status).json(response.message);
    });
}

用于添加POST的

代码语言:javascript
复制
module.exports.techDetailsAddOne = function (req, res) {
  const projectId = req.params.projectId;

  let newTechDetails = getTechDetailsFromBody(req.body);

  Project
  .findByIdAndUpdate(projectId,
    { '$push': { 'techDetails': newTechDetails } },
    {
      'new': true,
      'runValidators': true
    },
    function (err, project) {
      let response = { };

      if (err) {
        response = responseDueToError(err);
      } else if (!project) {
        response = responseDueToNotFound();
      } else {
        response.status = HttpStatus.CREATED;
        response.message = project.techDetails;  // for example
      }

      res.status(response.status).json(response.message);
    });
}

用于使用PUT进行更新

代码语言:javascript
复制
module.exports.techDetailsUpdateOne = function (req, res) {
  const projectId = req.params.projectId;
  const techDetailId = req.params.techDetailId;

  let theseTechDetails = getTechDetailsFromBody(req.body);
  theseTechDetails._id = techDetailId;  // can be skipped if body contains id

  Project.findOneAndUpdate(
    { '_id': projectId, 'techDetails._id': techDetailId },
    { '$set': { 'techDetails.$': theseTechDetails } },
    {
      'new': true,
      'runValidators': true
    },
    function (err, project) {
      let response = { };

      if (err) {
        response = responseDueToError(err);
        res.status(response.status).json(response.message);
      } else if (!project) {
        response = responseDueToNotFound();
        res.status(response.status).json(response.message);
      } else {
        project.save(function (err) {
          if (err) {
            response = responseDueToError(err);
          } else {
            response.status = HttpStatus.NO_CONTENT;
          }

          res.status(response.status).json(response.message);
        })
      }
    });
}

和删除:

代码语言:javascript
复制
module.exports.techDetailsDeleteOne = function (req, res) {
  const projectId = req.params.projectId;
  const techDetailId = req.params.techDetailId;

  Project
    .findById(projectId)
    .select('techDetails')
    .exec(function (err, project) {
      let response = { }

      if (err) {
        response = responseDueToError(err);
        res.status(response.status).json(response.message);
      } else if (!project) {
        response = responseDueToNotFound();
        res.status(response.status).json(response.message);
      } else {
        let techDetail = project.techDetails.id(techDetailId);

        if (techDetail !== null) {
          project.techDetails.pull({ '_id': techDetailId });

          project.save(function (err) {
            if (err) {
              response = responseDueToError(err);
            } else {
              response.status = HttpStatus.NO_CONTENT;
            }

            res.status(response.status).json(response.message);
          })
        } else {
          response = responseDueToNotFound();
          res.status(response.status).json(response.message);
        }
      }
    });
}

和最终路由如下:

代码语言:javascript
复制
router
    .route('/projects')
    .get(ctrlProjects.projectsGetAll)
    .post(ctrlProjects.projectsAddOne);

router
    .route('/projects/:projectId')
    .get(ctrlProjects.projectsGetOne)
    .put(ctrlProjects.projectsUpdateOne)
    .delete(ctrlProjects.projectsDeleteOne);

router
    .route('/projects/:projectId/techDetails')
    .get(ctrlTechDetails.techDetailsGetAll)
    .post(ctrlTechDetails.techDetailsAddOne);

router
    .route('/projects/:projectId/techDetails/:techDetailId')
    .get(ctrlTechDetails.techDetailsGetOne)
    .put(ctrlTechDetails.techDetailsUpdateOne)
    .delete(ctrlTechDetails.techDetailsDeleteOne);

当我不断地独立于文档的其他部分更新子文档时,我更喜欢这样做。它不创建单独的集合,因此不需要填充。

编辑:This答案将更详细地说明您是应该使用嵌入还是引用。我的答案是嵌入。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46840583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档