mongodb _id with graphql and document.toObject() - javascript

Let's use a basic mongodb query that returns one item:
const result = await db.myCollection.findById('xxxx')
return result;
This query result given to graphql works fine.
But now, if I return a result.toObject(), it's not working anymore.
I got this following error:
"message": "Cannot return null for non-nullable field MyCollection.id."
Why with toObject(), the mapping between _id and id can't be done?

The id generated by MongoDB will be a _id field -- it's mongoose that's actually mapping it for you.
Mongoose assigns each of your schemas an id virtual getter by default
which returns the documents _id field cast to a string, or in the case
of ObjectIds, its hexString. If you don't want an id getter added to
your schema, you may disable it passing this option at schema
construction time.
They key here is that the id field is a virtual getter. In order to include those in the generated object, you have to pass the appropriate option to toObject:
result.toObject({ virtuals: true })
See the docs or this answer for more details.

Related

Cloud Firestore: Get Value from collection ID if it exists

I want to obtain the value of a collection ID from a collection in cloud firestore if it exists:
export const getSlugs = async () => {
const document = await db
.doc(constDocumentRefs.slugs)
.collection('<collection_id>')
return ;
};
but this returns me collection reference, I can check if its empty by calling: document.get().empty method but not sure how do I get the value of collection, in case it is not empty.
My collection looks like this:
{
key1:1
key2:2
}
I want to keep it like return the actual value if collection exists otherwise return -1. Someone please help!
I can see two possible ways:
From the front-end:
As Dharmaraj mentioned in his comment, you need to fetch document(s) in the collection to see if the querySnapshot is empty or not. If the snapshot is empty, the collection does not exist. You can limit the query to only one document to minimize cost. For that you'll use the limit() method. And for checking if the QuerySnapshot contains a doc use the size property.
From a back-end:
The Admin SDKs offer a specific method to list collections, for example listCollections() for the Node.js Admin SDK (and listCollections() method of a DocumentReference for listing sub-collections). You can implement that in a Cloud Function and call it from your front-end: I wrote an article on this approach.

Pass an object to update fields on MongoDB

I need to pass to the updateMany method in a Node/Typescript software a piece of query retrieved from the database:
{'$unset': {'extras' : {'origin': ''}}}
In the db, the above query is stored as a field of an Object:
"cleanup.aggregated_records_to_modify" : {
"update_fields_by" : "{'$unset': {'extras' : {'origin': ''}}}"
}
If I pass the update_fields_by to the updateMany mondodb Nodejs driver method, I have an error saying ""MongoError: the update operation document must contain atomic operators." (it receives a string instead of an object?!?); if, instead, I create an object variable:
const queryTemp = { $unset: { extras: { origin: "" } } };
to give to the updateMany, all goes well.
How can I retrieve the field from db and correctly pass it to the update method as an object?
If you use JSON.parse(foo) on your variable, to convert it from string to an object
There was a problem (a bug?) with the tool I use to manage MondoDB; I cannot store an object with a key starting with $ because I receive the error "Illegal argument: Invalid BSON field name $unset". I have add the $ symbol programmatically.

Ember data changing primaryKey for a model from id to something else

Currently I have a model setup like this
App.Specialty = DS.Model.extend({
//specialty_id: attr(),
name: attr()
});
It has a primaryKey being returned from the json api called specialty_id instead of id (what ember data probably expects).
So not fiddling with anything ember data gets two objects where one it uses the id as whatever parameter and the second one it gets the right object but has id as undefined.
How can I let ember data know that it should be searching for specialty_id instead?
For the entire app
App.ApplicationSerializer = DS.RESTSerializer.extend({
primaryKey: '_id'
});
For a single type
App.FooSerializer = DS.RESTSerializer.extend({
primaryKey: '_id'
});
You will still refer to it as id on the model, but Ember Data will serialize/deserialize it to _id during transfer.
Example: http://emberjs.jsbin.com/OxIDiVU/635/edit
Read More about it here: http://emberjs.com/api/data/classes/DS.RESTSerializer.html#property_primaryKey

Mongoose find() not returning result

I have a route set up that uses a model called Todo like below:
app.get('/api/todos', function(req, res) {
Todo.find({},function(err, todos) {
if (err)
res.send(err);
console.log("number of todos " + todos.length);
res.json(todos); // return all todos in JSON format
});
});
however, todos.length is always 0, as it do not find any results.
When I run:
use test3
db.Todo.find()
I am sure I have connected to the same db. I can see the connection in mongod console.
My connection is inside config/db.js file:
module.exports = {
url : 'mongodb://localhost/test3'
}
The connection in my server.js is as follows:
var db = require('./config/db');
mongoose.connect(db.url);
in Mongo Shell I get 1 result. I am expecting this result to be return by the find query.
Is there something I have missed?
I am using Mongoose 3.6
Cheers
So what this very much looks like is that you have already created collections in an existing database and now you are trying to access these with mongoose models.
The problem is that mongoose uses some defaults which you may not be aware of, so the example you are showing from the shell is not the same as what mongoose is doing by default.
So you can either rename your collections to match what mongoose expects by default or change what mongoose does to match your existing names. In the latter case, you directly define the model names like so:
mongoose.model( "Todo", toDoSchema, "Todo" );
So the third argument to the method actually specifies the explicit name to use for the collection. Without this the assumed name under the default rules will be "todos".
Use either method in order yo make them match.
I faced this exact issue, I defined the Model for an already existing collection in MongoDB and to stop Mongoose from producing a collection name in plural I used this explicit collection option. Mistakenly I wrote Collection and this halted the results. So be careful while using explicit options, they are case sensitive.

MongoDB findAndModify() adds query to update clause

I'm creating an application in Node that has some CRUD components. On one of my data objects, I have a save() method that is meant to update a record if the object has an id that is found in the collection, or upsert a new document if not. Additionally, if doing an upsert I'd like to get back the _id for the document generated by Mongo.
It seems that findAndModify would do this, and, indeed, it does return an _id value from the database. In my query clause, I am filtering by _id. If my data object doesn't have an id, Mongo correctly does an upsert, however, no matter what _id value it returns, in addition to the the keys I am setting in the update clause, it also sets the _id on the document based on what value I used in the query clause. Some code for clarity:
User.prototype.save = function(callback) {
var that = this;
var args = {
'query' : { _id: this.getId() }, //getId() returns empty string if not set
'update' : { $set : {
firstName : this.firstName,
lastName : this.lastName,
email : this.email
//_id : this.getId()
// which is blank, is magically getting added due to query clause
}},
'new' : true,
'upsert' : true,
'fields' : {'_id' : true}
};
this.db.collection(dbName).findAndModify(args, function(err, doc){
if(!that.getId()) {
that.setId(doc._id);
}
if (typeof(callback) === "function"){
callback.call(that);
}
});
}
I'm simply looking for the semantics of update that also happens to return a Mongo-generated _id on upsert. I do not want the values of the query clause to additionally be appended as if they were in the update map. Is there any way to achieve what I am getting at?
You can generate the _id client side, with new new require('mongodb').ObjectID()
Then you can just do a regular upsert (no need to do findandmodify) because you already have the _id.
However, if you are using findAndModify, keep in mind that the node driver accepts the arguments to this function positionally, not as an object (like in the regular mongo shell).
The correct format to do findandmodify with the node driver looks like this:
collection.findAndModify(criteria, sort, update[, options, callback])
(options and callback are optional params). Full docs here:
https://github.com/mongodb/node-mongodb-native/blob/master/docs/insert.md

Categories