Info
We are migrating our server from forest-express-mongoose
to Node.js
. We have not yet figured out a way to create a relationship from an array of IDs, previously done with a route. I will give an example below and also show some code snippets.
Based on the code explanation and code snippets below, the question is:
How do we achieve the same thing as before without adding userId to venue documents?
Setup explanation
We have 3 different collections, Users, Merchants, and Venues.
Users β Merchant (many β 1). Reference = user.manages.merchantId
Venues β Merchant (many β 1). Reference = venue.merchantId
We wish to create a smart relationship from Users to Venues, which would become an array of references to multiple venues that we manually have to calculate.
Solution before migrating, using routes
We created a custom smart relationship between User and Venues, returning an array of references.
router.get('/users/:userId/relationships/venues', async (req, res, next) => {
const user = await users.findOne({
_id: mongoose.Types.ObjectId(req.params.userId),
});
let venuesList = [];
const merchant = await merchants.findOne({
_id: user.manages.merchantId,
});
venuesList.push(...(await venues.find({ merchantId: merchant._id })));
const serializer = new RecordSerializer({ name: 'venues' });
res.send(
await serializer.serialize(venuesList, {
count: venues.length,
}),
);
});
How we would like to do it now in the new Node.js version
We get the following error when running the code below: Error Types from 'User.venuesIds' and 'Venue._id' do not match.
.customizeCollection('User', collection => {
collection.addField('venuesIds', {
columnType: ['String'],
dependencies: ['manages@@@merchantId'],
getValues: async (users, context) => {
const venues = context.dataSource.getCollection('Venue');
const relatedVenues = await venues.list(
{ conditionTree: { field: 'merchantId', operator: 'In', value: users.map(m => m['manages@@@merchantId']) } },
['_id', 'merchantId'],
);
return users.map(record => {
return relatedVenues.filter(ven => ven.merchantId === record['manages@@@merchantId']).map(ven => ven._id);
});
},
});
collection.replaceFieldOperator('venuesIds', 'In', async (venueIds, context) => {
const records = await context.dataSource
.getCollection('Venue')
.list({ conditionTree: { field: '_id', operator: 'In', value: venueIds } }, ['_id']);
return { field: 'venuesIds', operator: 'In', value: records.map(r => r._id) };
});
collection.addManyToOneRelation('venues', 'Venue', {
foreignKey: 'venuesIds',
foreignKeyTarget: '_id',
});
})
Context
- Project name: PayAtt Internal Admin Portal
- Team name: All teams
- Environment name: All environments
- Agent (old): forest-express-mongoose: ^8.7.9
- Agent (new):
"@forestadmin/agent": "^1.13.4",
&"@forestadmin/datasource-mongoose": "^1.4.2",
- Database type: MongoDB Atlas