TypeORM MongoDB populate - node.js

I'm currently playing around with NestJS and am using MongoDB with TypeORM, and I couldn't find something similar to the .populate() method in Mongoose, is there a way to do it with TypeORM or should I stick to Mongoose?
For example, here is a route I created with Express + Mongoose, and I want to recreate it with NestJS + TypeORM:
route.get('/:slug', async (req, res) => {
const collection = await Collection.findOne({slug: req.params.slug}).populate('products');
res.json(collection);
});

In TypeORM there is something called relations which you can use to populate the docs from other(related) collections.
Here is an example from TypeORM docs :
createConnection(/*...*/).then(async connection => {
/*...*/
let photoRepository = connection.getRepository(Photo);
let photos = await photoRepository.find({ relations: ["metadata"] });
}).catch(error => console.log(error));
You can read more about it here on TypeORM docs.
According to how you design collection/schema in TypeORM, your query might look like this, i havent tried the query but you can make it work like this:
Collection.find({slug: req.params.slug}, {relations : ['products']});
Note, there are also functions like .innerJoinAndSelect and .leftJoinAndSelect which you can use with QueryBuilder(.createQueryBuilder) and populate documents from other collection just like mongoose .populate()
I suggest that you read the TypeORM, there are many examples given as well, it will help you build the kind of query you need.

Related

Loop through collection and find documents where name equals in firebase functions

I am trying to make as much logic in the firebase cloud functions, but not sure how to! Here is what I am trying to accomplish:
const myGroups = admin.firestore().collection('groups').find({"playerId":userId});
I know that above is not correct, but i cant seem to find a solution for this. I would like to get all my groups into an array or something and send them back to my app.
I am not sure if this is wise?!? But think that it would be easier to add or change to the script from one place, instead of all devices.
Hi you need to use firestore compound queries you can find the documentation here: https://firebase.google.com/docs/firestore/query-data/queries
so in your case the code will look something like:
const myGroups = await admin.firestore().collection('groups').where("playerId", "==", userId}).get();
You can use get() on the CollectionReference to get all documents.
const myGroups = await admin.firestore().collection('groups').get()
return myGroups.docs.map(group => ({id: group.id, ...group.data()}))
Additionally, if you are trying to find groups where playerId is userId. Then you can use where() clause to narrow search results:
const myGroups = await admin.firestore()
.collection('groups')
.where("playerId", "==", userId)
.get()
You can read more about queries in the documentation.

How to use groupBy in Bookshelf js?

how to use groupBy in Bookshelf JS, here is my Controller code.
router.route('/fetchStudentAttendance')
.post(function(req, res) {
StudentAttendance
.query(function (qb){
qb.where('date', '>=', req.body.date);
qb.groupBy("students_id");
})
.where({'class_id': req.body.class_id, 'section_id': req.body.section_id})
.fetchAll({ withRelated: [{'StudentRef':function(qb) {qb.column('id', 'first_name', 'middle_name', 'last_name')}}]})
.then(studentAttendance => {
let content = {
data: studentAttendance,
success: true,
message: 'Record Not Found',
};
return res.send(content);
})
.catch(error => {
let content = {
data: error,
success: false,
message: 'Error while fetching Student Attendance.',
};
return res.send(content);
});
});
when i am trying to "groupBy" employee_id it will give Error like this.
code:"42703"
file:"parse_relation.c"
length:110
line:"3194"
name:"error"
position:"127"
routine:"check_ungrouped_columns_walker"
severity:"ERROR"
TL;DR
Use Bookshelf's built-in Collection manipulation to do custom groupBy after the .fetchAll()
OR
Use raw Knex to generate your query and results as needed, since groupBy will require some SQL aggregation definitions. This can be a Knex query result, or a Bookshelf object.
More Words
Bookshelf isn't exactly a query generator; not like the query libray KnexJS it is built off of. Bookshelf is made as a way to collect rows from your DB as Object Models. A SQL "groupBy" clause is kind of custom to the query, and Bookshelf itself implements lodash methods, like lodash's groupBy as stated in their docs. However, that is a server-side grouping on the queried data, it is not using SQL to do so.
When using your Model in Bookshelf, you should use new Model or Model.forge() before you fetch (or in case of many, .fetchAll()). You can start a Knex query, in a way, by using Model.query (see docs), but be aware that is returning Bookshelf objects. I typically use .query(function (qb) {}) to do some custom knex, like a custom WHERE clause or an qb.orderBy('prop'). Since groupBy would include 'many', you would want Model.query().fetchAll(), and be aware of custom aggregation in that query (Bookshelf will likely handle it, but it wouldn't be exactly like the model you defined, especially with custom methods). Using Knex directly might be a good option too.

How to get the defined indexes from Mongoose

I have been trying to find out the indexes which are already created via MongoDB manually( I have created 2d sphere indexes for two fields via mongobooster and creating one via schema by defining it). Now if i run this query in mongodbooster
db.collectionname.getIndexes();
It results me the 3 documents with name.key and which indexes i have used. I want to perform this same operation in mongoose i can't find a equivalent query for the same. I tried this
const indexes = OrderSchema.indexes();
console.log('index:', indexes);
But it gives me only one index which i have defined in schema that is _id i need two other fields as well which contains 2d-sphere index how can i get that too. What am trying to achieve here is if 2d sphere indexes are already created don't create an index else create an index that's all am trying to achieve here. Any help is appreciated Thanks
Yeah, you can't do it with a schema. You will need to create the model first, and then you can do something like this:
Order.collection.getIndexes({full: true}).then(indexes => {
console.log("indexes:", indexes);
// ...
}).catch(console.error);
If you dont have access to mongoose model, but the mongoose connection was created and you need to get the indexes from a collection you can access by this way:
const mongoose = require('mongoose');
mongoose.connect('myConnectionString', { useNewUrlParser: true }).then(() => {
getIndexes();
});
const getIndexes = async () => {
const indexes = await mongoose.connection.db.collection('myCollection').
indexes.forEach(function (index) {
console.log(JSON.stringify(index));
});
};

How do you find by id using the MongoDB Node driver?

I'm looking for the best way to find by id using the MongoDB Node driver.
I see that the _id field is an ObjectId, and so using a string for the id won't work. And I see that you could use ObjectId as follows:
var ObjectId = require('mongodb').ObjectId;
exports.show = function(req, res) {
var db = req.app.get('db');
var id = new ObjectId(req.params.id);
db.collection('posts').findOne({
_id: id
}, function(err, post) {
res.status(200).json(post);
});
};
But is there a best practice/more convenient way? I hadn't come across one in looking through the docs. Note: Mongoose has a findById method where you could just use the id string.
The _id field is already indexed, and findByID implicitly searches for one document, hence, findOne where you'll pass options {_id: id} as you're already doing.
As far as I understand, the major design consideration was to make native driver API similar to the mongo shell experience and keep it consistent all over the place (other drivers as well?). For this purpose you might want to keep API simple, yet powerful to cover all cases. So, to generalize, you have find() method and "a db.collection.findOne() method as a special case of find() that returns a single document."

How can I combine Schema and noSchema with Mongoose?

I know I have to define Schema's in Mongoose, but I have a case where I'm connecting to a MongoDB via
dsn = "mongodb://#{config.database.username}:#{config.database.password}##{config.database.host}/{config.database.name}"
mongoose.connect(dsn, (err) -> throw err if err)
And most of my writes will be using Models the way I'm supposed to. But there is this one read that I have to do from a Collection and it's Schema-less. Meaning, it's unprocessed data that was stored by another process. How can I successfully read from that then write to other collections using my Schemas?
If I use mongoose, can I not do this?
To start with you can just make a blank schema for it.
var OtherSchema = new Schema({}, {collection: 'your-collection-name'});
Mongoose.model('Other', OtherSchema);
// ..

Resources