mongodbgraphqlapollo-clientmongodb-stitch

MongoDB Stitch GraphQL Custom Mutation Resolver returning null


GraphQL is a newer feature for MongoDB Stitch, and I know it is in beta, so thank you for your help in advance. I am excited about using GraphQL directly in Stitch so I am hoping that maybe I just overlooked something.

The documentation for the return Payload displays the use of bsonType, but when actually entering the JSON Schema for the payload type it asks for you to use "type" instead of "bsonType". It still works using "bsonType" to me which is odd as long as at least one of the properties uses "type".

Below is the function:

      const mongodb = context.services.get("mongodb-atlas");
      const collection = mongodb.db("<database>").collection("<collection>");
      const query = { _id: BSON.ObjectId(input.id) }
      const update = {
        "$push": {
          "notes": {
            "createdBy": context.user.id, 
            "createdAt": new Date, 
            "text": input.text
          }
        }
      };

      const options = { returnNewDocument: true }

      collection.findOneAndUpdate(query, update, options).then(updatedDocument => {
        if(updatedDocument) {
      console.log(`Successfully updated document: ${updatedDocument}.`)
    } else {
      console.log("No document matches the provided query.")
    }
    return {
      _id: updatedDocument._id,
      notes: updatedDocument.notes
    }
  })
  .catch(err => console.error(`Failed to find and update document: ${err}`))
}

Here is the Input Type in the customer resolver:

  "type": "object",
  "title": "AddNoteToLeadInput",
  "required": [
    "id",
    "text"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "text": {
      "type": "string"
    }
  }
}

Below is the Payload Type:

{
  "type": "object",
  "title": "AddNoteToLeadPayload",
  "properties": {
    "_id": {
      "type": "objectId"
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "createdAt": {
            "type": "string"
          },
          "createdBy": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        }
      }
    }
  }
}

When entering the wrong "type" the error states:

Expected valid values are:[array boolean integer number null object string]

When entering the wrong "bsonType" the error states:

Expected valid values are:[string object array objectId boolean bool null regex date timestamp int long decimal double number binData]

I've tried every combination I can think of including changing all "bsonType" to "type". I also tried changing the _id to a string when using "type" or objectId when "bsonType". No matter what combination I try when I use the mutation it does what it is supposed to and adds the note into the lead, but the return payload always displays null. I need it to return the _id and note so that it will update the InMemoryCache in Apollo on the front end.


Solution

  • I noticed that you might be missing a return before your call to collection.findOneAndUpdate()

    I tried this function (similar to yours) and got GraphiQL to return values (with String for all the input and payload types)

    exports = function(input){
    
      const mongodb = context.services.get("mongodb-atlas");
          const collection = mongodb.db("todo").collection("dreams");
          const query = { _id: input.id }
          const update = {
            "$push": {
              "notes": {
                "createdBy": context.user.id, 
                "createdAt": "6/10/10/10",
                "text": input.text
              }
            }
          };
    
          const options = { returnNewDocument: true }
    
    return collection.findOneAndUpdate(query, update, options).then(updatedDocument => {
            if(updatedDocument) {
          console.log(`Successfully updated document: ${updatedDocument}.`)
        } else {
          console.log("No document matches the provided query.")
        }
        return {
          _id: updatedDocument._id,
          notes: updatedDocument.notes
        }
    
      })
      .catch(err => console.error(`Failed to find and update document: ${err}`))
    }