How to display nested graphql object datatypes given mongoDB objectID? - mongodb

I am writing an app with GraphQL and mongoose. I created a function to get all bookings inside MongoDB. A booking object contains a reference to another object called Service. When I store a booking, it will store the associated service object as an ObjectID in MongoDB. When I make a query in graphql to get all the bookings, graphql does not services and their field types since graphql only receives an objectID. How can I fix graphql?

You need to write a resolver for the serviceType in AppointmentBooking.
Query: {
async getAppointmentBookings() {
...
}
},
Mutation: {
...
},
AppointmentBooking: {
serviceType: async(parent, args, ctx, info) => {
// Here you will get the objectId from the parent that need to query services
// This will call for every object inside the bookings
// Assuming you are storing the objectID for the services in the key servicetype
const serviceId = parent.serviceType;
try {
const serviceDetails = await Sevice.findByID(serviceID) ;
return serviceDetails;
} catch (err) {
throw new Error(err);
}
}
}

Related

How do you find a document by id in a MongoDB Realm Function?

I'm writing a function in MongoDB Realm that I want to use as a custom resolver for GraphQL. Part of the function should get a specific document by its id. According to the documentation I can get access to the Atlas DB by using context.services.get('mongodb-atlas'). Here's the simplified code extract:
exports = async () => {
const cluster = context.services.get('mongodb-atlas');
const collection = cluster.db('my-db').collection('my-coll');
return await collection.findOne({"_id": "61d33d2059c38ef0584c94f8"});
}
However, the findOne() call returns null. I know that the id above is valid, because I can successfully call collection.find() and list all the documents with their ids.
What I've tried
findOne({"_id": "61d..."}) - returns null
findOne({"_id": new ObjectId("61d...")}) - error: "ObjectId" is not defined.
Explicitly declaring ObjectId with const ObjectId = require('mongodb').ObjectId as recommended here - error: "MongoDB Node.js Driver is not supported".
Declaring ObjectId with const ObjectId = require('bson').ObjectId - findOne() returns null again.
Can you recommend any other avenue by which to do this lookup?
First thing I would suggest is - let's identify where the script is failing.
We know for certain, the below should work.
exports = async () => {
let tmp_collection = context.services.get("mongodb-atlas").db("my-db").collection("my-coll");
return await tmp_collection.findOne({});
}
After you can confirm that the above works, give this a try:
return await context.services.get("mongodb-atlas").db("my-db").collection("my-coll").findOne({"_id":new BSON.ObjectId("61d33d2059c38ef0584c94f8")});
Here is your code, but fixed:
exports = async () => {
const cluster = context.services.get('mongodb-atlas');
const collection = cluster.db('my-db').collection('my-coll');
return await collection.findOne({"_id": new BSON.ObjectId("61d33d2059c38ef0584c94f8")});
}

How to send ISODate in meteor.call method

I am creating an array of objects in client side in the meteor, and each object have modified date inside it as mentioned below:
Client Side:
student;
here student is an array of an object contains name, id, roll_no
var array = [];
student.forEach(function(singleStud, index){
var single_obj ={
"name":singleStud.name,
"student_id":singleStud.id,
"roll_no":singleStud.roll_no,
"college_name":"ABC college",
"college_id":"xyz Id",
"created_date": new Date()
}
array.push(single_obj);
},this)
Meteor.call('saveDetails', array, function (error, result) {
console.log("data Saved Successfully");
});
Server Side:
I have used plugin mikowals:batch-insert to insert an array which is equivalent to insertMany in mongo.
Meteor.methods({
"saveDetails": function (array) {
try {
studentDetails.batchInsert(array);
return true;
} catch (err) {
return err;
}
}
});
when I save it the created_date is saving it as a string ("2018-04-23T10:26:26.766Z"), but I want it to be saved it as a date data type (ISODate("2018-04-23T10:26:26.766Z")).
How can I achieve from the client side in meteor.call ???
This is actually a bug in mikowals:batch-insert. mikowals-batch-insert recursively attempts to convert objects into a JSON format friendly with MongoDB. As part of this process, it uses underscore clone to make shallow copies of primitive types. While Date is a primitive, it cannot be cloned with _.clone, so it mutates your date to a string (eww). You should open an issue with mikowals:batch-insert.
Regardless, you shouldn't be defining this data on the client. The client could maliciously inject false information (which could break your application's logic). Instead, you should map over the input and inject the date into incoming objects.

TypeORM FindById doesn't work with MongoDB

I'm trying to use TypeORM with MongoDB and express but I'm having problems with the basic stuff.
I just created a controller with basic CRUD operations for an entity. The methods save, findAll and find by Filter works ok, but I can't make the methods that require an mongo id work.
router.get("/", async(req: Request, res: Response) => {
const investmentRepository = getMongoRepository(Investment);
const investments = await investmentRepository.find();
res.send(investments);
});
router.get("/:id", async(req: Request, res: Response) => {
const investmentRepository = getMongoRepository(Investment);
const investment = await
investmentRepository.findOneById(req.params.id);
if (!investment) {
res.status(404);
res.end();
}
res.send(investment);
});
The second method is always returning 404.
For example, this is an entity returned on get all "investment/"
{
"id": "59dfd8cadcbd9d1720457008",
"name": "Teste LCI",
"startDate": 1466305200,
"numberOfDays": 365,
"type": "LCI_LCA"
}
If I try to send a request for this specific object calling
investment/59dfd8cadcbd9d1720457008
the response is always 404.
The same behavior happen with the delete method, raising an exception
Cannot find entity to remove by a given id
I also tried to convert the string to ObjectID using:
new ObjectID(req.params.id);
but it fails with the error ObjectID is not a constructor.
If you're receiving the error ObjectId is not a constructor it is because you forgot to require it in your file. All you need is:
const ObjectId = require('mongodb').ObjectId;

Overwrite object in mongodb

This should be simple but it is surprisingly difficult and extremely frustrating. I am trying to overwrite an 'Object' field in mongodb with a new Object that the user creates in my client webpage. I have validated that all other fields I am passing to the update operation are in fact being updated, with the exception of the javascript object. Instead of it updating with the object I am passing (While I validated is being populated with the object I am passing through), it just updates it back to {} instead of whats being passed:
{ nodes:[ { w: 120, h: 80,type: 'InHive',left: 184,top: 90,text: 'item',query: 'hey',name: 'sample',id: '7686132d-6fcf-4a3b-baa2-b1c628e0b2d6' } ], edges: [], ports: [],groups: [] }
When I attempt to update the data field outside of the meteor method, directly from the mongo console interface, it overwrites that field successfully with the javascript object. What am I doing wrong here, because I cant for the life of me figure this one out?
Server Method
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
MYCOLLECTION.update({
_id: id
}, {
$set: {
[field]: object, //this just gets reset back to {} whenever this update method is called
"metadata.last_modified_dt": new Date(), //this gets updated
"metadata.modified_by": Meteor.userId(), //this gets updated
'metadata.modified_by_username': _username //This gets updated
}
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
Client Call:
var _jsonformat = toolkit.exportData();
var currentid = Session.get('rulesRowClicked')._id;
console.log(_jsonformat);
Meteor.call('updateOneWorkflow' , currentid, 'data', _jsonformat, function(err, res){
if(err){
toastr.error('Failed to save result ' + err);
}
else{
toastr.success('Saved workflow');
}
});
I believe your problem is stemming from this line: [field]: object. I don't believe that's a proper method of dynamically accessing an object's field. Instead, try to dynamically update the field as so:
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
var newObj = {
"metadata": {
"last_modified_dt": new Date(),
"modified_by": Meteor.userId(),
"modified_by_username": _username
}
};
newObj[field] = object;
MYCOLLECTION.update({
_id: id
}, {
$set: newObj
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
The issue was crazier than I expected. If you are using Meteorjs and you are using the Aldeed Schema 2 collection framework, it seems to completely ignore updates/inserts of json objects even if you set the field type to Object, unless you set up the exact same schema as the object (including nested array objects) and attach it to your collection. Dumbest thing Ive ever seen, no idea why nothing warns you of this. I removed the schema attachment and it worked.

Mongodb for HL7-FHIR

Learning FHIR and trying to implement with MEAN stack which uses MongoDb as database, I would like to seek your help on my question.
When I get the POST request for a new resource docment, I will insert it into MongoDB. Since the MongoDB will add the _id (object id) to the resources as a unique id. When I retrieve the document, it will have the extra field _id. I think it will make the resources not compliance any more since the _id is not defined in the resources.
May I know how to handle this issue? Will this extra _id matter in the FHIR resource?
Best regards,
Autorun
So, I'm also using MongoDB - along with mongoose - to implement FHIR in nodejs.
I've just added a field called id in the schema definition for mongoose like this
import mongoose from 'mongoose';
import shortid from 'shortid';
class resource extends mongoose.Schema {
constructor(schema) {
super();
this.add({
// just added this to make MongoDB use shortid
_id: { type: String, default: shortid.generate },
id: { type: {} },
id_: { type: {} },
implicitRules: { type: String },
implicitRules_: { type: {} },
language: { type: String },
language_: { type: {} },
...schema
});
}
}
export default resource;
and then _id field takes its value from the id when create/update a resource
my code for upserting a patient resource
upsert(root, params, context, ast) {
const projection = this.getProjection(ast);
if (!params.data.id) {
params.data.id = shortid.generate();
}
params.data.resourceType = 'Patient';
const upserted = model
.findByIdAndUpdate(params.data.id, params.data, {
new: true,
upsert: true,
select: projection
})
.exec();
if (!upserted) {
throw new Error('Error upserting');
}
return upserted;
}
yes, the _id will not be conformant. You can't change it to 'id'?
Perhaps you can take a look at the Spark server, which also uses a MongoDB to store the resources. In the Spark.Store.Mongo namespace you will see some helper methods to convert a Mongo BSONdocument to a FHIR resource.