Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to change MongoDB collection dynamically, based on context data #2603

Closed
desaroger opened this issue Aug 10, 2016 · 5 comments
Closed

How to change MongoDB collection dynamically, based on context data #2603

desaroger opened this issue Aug 10, 2016 · 5 comments
Labels

Comments

@desaroger
Copy link

Overview

I want to change my models collection on MongoDB dynamically for each call. And besides that, I want to be a decision based on the context data. Related: I opened other issue (#2597) where I have problems obtaining the context on observers, and the proposal was the #1676, but this proposal doesn't solve the problem of changing of mongodb collection.

Why?

Simplifying, we have some models (say Cars, Parts ...). We have a model Distributor, which have related cars, parts, etc. We serve our Api to a third party distributors, so they can use his api. But we want to hide all the api outside his /Distributors/{id}/, so we thought a good way would be change the collection names, so if we have model Cars and a distributors GET /Cars, they send on the header the DistributorID and we changes the collection's names for this call.

Besides of our desire to hide this part of the url api, we think this approach would be a good option to isolate on different collections the data of different distributors, so simplify debug/security.

How I tried?

My attempt was to override the method "collectionName" on mongoDB adapter. This function originally looks for the collectionName on the model settings, and if not found returns the model name. I want to change this behavior.

I override this function and works fine and with context some times, but other times I have no context.

Sandbox

I created a sandbox repo. On banch change-collection you can see my attempt to change the collection. (file /server/boot/steps/11.change-collection.js). The sandbox repo is a different example using pokémons and not distributors/cars, but the issue with the collections is the same.

My results

change-collection get
change-collection put

As you can see, I have context on the observers thanks to the workaround, but on the mongodb function the workaround is not applicable, so loopback.getCurrentContext() is used. When mongo looks for the collection of AccessToken there is context, but not for ACL or Pokemon.

For some reason on GET methods, Pokemon has no context at all, but on PUT methods I has context when the collection of Pokemon is required, but these context isn't the same context of the rest application.

Another ways

I understand that the context on loopback has many issues and this "hack" to change the collection of mongo is a bad practice. And probably in a near future we migrate to a simpler relation option, and maybe with a url alias we can hide the "private" side of the api. But we want to try this approach and to understand why sometimes there is no context and sometimes there is. And this issue can be a reference to people that are trying to make this too.

Thanks in advance for your help.

@desaroger
Copy link
Author

Finally I could solve my issue with the context. I had to make a modification to loopback-connector-mongodb as on two points of the code the context was losing the binding.

I made a PR to loopback-connector-mongodb to patch the context issue. With this patch and the usage of cls-hooked all my issues has been solved.

Thanks to all anyway.

@davidcheung
Copy link
Contributor

Looks like the underlying issue is not on our end, but as this remains to affect loopback it might be useful for this issue to stay alive.
loopbackio/loopback-connector-mongodb#275 (comment)

Instead, the fix should be implemented in the MongoDB client library we are using under the hood. Since cls-hooked is based on AsyncWrap that's becoming the standard part of Node.js core, I expect it's fair to ask the MongoDB client to play nicely with AsyncWrap. The same way how it already supports domains.

@bajtos
Copy link
Member

bajtos commented Jan 9, 2017

The new solution for context propagation has been implemented and released, see #1495 and #3023.

loopback-context is known to have issues with the MongoDB connector, let's keep that discussion in strongloop/loopback-context#21.

I am closing this issue.

@bajtos bajtos closed this as completed Jan 9, 2017
@bvenky27
Copy link

Overview

I want to change my models collection on MongoDB dynamically for each call. And besides that, I want to be a decision based on the context data. Related: I opened other issue (#2597) where I have problems obtaining the context on observers, and the proposal was the #1676, but this proposal doesn't solve the problem of changing of mongodb collection.

Why?

Simplifying, we have some models (say Cars, Parts ...). We have a model Distributor, which have related cars, parts, etc. We serve our Api to a third party distributors, so they can use his api. But we want to hide all the api outside his /Distributors/{id}/, so we thought a good way would be change the collection names, so if we have model Cars and a distributors GET /Cars, they send on the header the DistributorID and we changes the collection's names for this call.

Besides of our desire to hide this part of the url api, we think this approach would be a good option to isolate on different collections the data of different distributors, so simplify debug/security.

How I tried?

My attempt was to override the method "collectionName" on mongoDB adapter. This function originally looks for the collectionName on the model settings, and if not found returns the model name. I want to change this behavior.

I override this function and works fine and with context some times, but other times I have no context.

Sandbox

I created a sandbox repo. On banch change-collection you can see my attempt to change the collection. (file /server/boot/steps/11.change-collection.js). The sandbox repo is a different example using pokémons and not distributors/cars, but the issue with the collections is the same.

My results

change-collection get
change-collection put

As you can see, I have context on the observers thanks to the workaround, but on the mongodb function the workaround is not applicable, so loopback.getCurrentContext() is used. When mongo looks for the collection of AccessToken there is context, but not for ACL or Pokemon.

For some reason on GET methods, Pokemon has no context at all, but on PUT methods I has context when the collection of Pokemon is required, but these context isn't the same context of the rest application.

Another ways

I understand that the context on loopback has many issues and this "hack" to change the collection of mongo is a bad practice. And probably in a near future we migrate to a simpler relation option, and maybe with a url alias we can hide the "private" side of the api. But we want to try this approach and to understand why sometimes there is no context and sometimes there is. And this issue can be a reference to people that are trying to make this too.

Thanks in advance for your help.

I have similar requirement as yours and I'm following your workaround but I couldn't find the method 'collectionName' to override. Can anyone help me in finding this method and also the changes to be made for the method 'collectionName'

@bvenky27
Copy link

I have similar requirement as yours and I'm following your workaround but I couldn't find the method 'collectionName' to override. Can anyone help me in finding this method and also the changes to be made for the method 'collectionName'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants