如何使用猫鼬“填充”来指定不同集合的现有文档的路径?

Posted

技术标签:

【中文标题】如何使用猫鼬“填充”来指定不同集合的现有文档的路径?【英文标题】:How to use mongoose "populate" to specify the path for already existing document of different collection? 【发布时间】:2018-11-08 03:24:04 【问题描述】:

我正在使用 Apollo Graphql、Express-Nodejs、MongoDB 和 Mongoose。我有 2 个集合,即:Business 和 Order。

这是模型

以下是 graphql 类型:

这里是突变:

createBusiness(
      name: String,
      address: String,
        ): Business

createOrder(
      orderNumber: String,
      businessName: String,
      additionalDetails: String
     ): Order

一个特定的业务可以有多个订单,一个特定的订单必须有一个特定的业务。

我想做的是为业务文档创建一个订单。

案例 1.) 如果业务文档不存在: 那么 createOrder 突变应该创建新的业务文档(通过使用填充)

案例 2。)但是如果业务文档存在,那么 createOrder 突变不应该创建新的业务文档,而只会添加新订单和对现有业务文档的引用。

有人可以告诉我如何在 graphql 和 mongoose 中实现上述要求吗?任何建议都会有所帮助!

这是我的 Order 变异解析器(它不工作,不知道为什么!!)

import Order from '../models/Order';
import Business from '../models/Business';

export default 

  Mutation:
    createOrder(_, 
      orderNumber,
      additionalDetails,
      businessName
    )
      return Business.findOne(
        businessName: businessName
      )
      .then((exist)=>

        if (!exist)

          let business_Name = new Business(
            name: businessName
          )

            business_Name.save(function (err)
              if (err) return handleError(err);

              let order = new Order(
                orderNumber: orderNumber,
                businessName: business_Name._id,
                additionalDetails: additionalDetails
              );

              order.save(function (err)
                if (err) return handleError(err);
              );
            );
        
        if (exist)
         // WHAT SHOULD I DO FOR THIS CASE ??
        



      );
    ,

  

提前致谢!

【问题讨论】:

【参考方案1】:

我稍微修改了案例 1 的逻辑,如果企业名称不存在,则不应允许创建订单。好像允许未经授权的人在 order 突变中创建业务,那么我们可能必须处理额外的可选参数(仅适用于案例 1),从而使“createOrder”突变更加麻烦且不那么合乎逻辑。

当业务存在时,我们会通知客户用户一些有用的消息,对于案例 1 和案例 2,我们会:

1.) 首先创建新订单,然后将其推送到 Business 类型的“订单”列表中,然后保存(因为 Business 类型需要对其子订单数组的引用)(阅读: Saving Refs to Children )

2.) 然后是时候保存新创建的订单并填充“businessReference”了。

这里是createOrder突变的完整代码...

createOrder:  async(_, 
    orderNumber,
    additionalDetails,
    businessName
  )=>
  // Check if the business  name exists or not 
    try 
            const business_name = await Business.findOne(
                                  name: businessName
                                  )
      if (!business_name)
        throw new Error ('Business name not found. Please create the Business first !');
      
  // if the business name exists, then 
  // first create order
        let order = await new Order(
                      orderNumber: orderNumber,
                      businessReference: business_Name._id,  
                      additionalDetails: additionalDetails
                  )

                  business_name.orders.push(order);   // then push this order to child
                  business_name.save();                 // array of Business for referencing
                                                        // it later


          return order.save()                                     //then save the order,
                      .then(res => Order.findById(res._id)          // and populate
                      .populate('businessReference')               
                      .exec())                                   

    
    catch (error) 
      throw error;
    
  

由于 exec() 只有在没有任何参数的情况下才会返回 Promise,所以我以这种方式返回它。有关这方面的更多信息,请查看 this awesome explained *** post

【讨论】:

以上是关于如何使用猫鼬“填充”来指定不同集合的现有文档的路径?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过填充字段在猫鼬中查找文档?

猫鼬填充 - 何时

猫鼬填充如何在同一对象而不是子文档中填充文档

如何正确初始化猫鼬集合中的文档

如何正确初始化猫鼬集合中的文档

构建猫鼬模式时如何引用不同集合中的特定字段?