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

Alt SPIKE: New objectid #596

Closed
wants to merge 9 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions SPIKE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ Ref: https://github.com/strongloop/loopback-next/issues/3456

## The Problem

`ObjectID` is a native MongoDB datatype, which is used as the datatype of its primary key (_id_) field; other fields
can also be of `ObjectID` type.
`ObjectID` is a native MongoDB datatype, which is used as the datatype of its primary key (_id_) field; other fields can also be of `ObjectID` type.

MongoDB distinguishes between id values that are a `strin` and an `ObjectID`. A query using a `string` value does not match records having `ObjectID` value and vice versa. This is especially important for foreign keys, e.g. when `Order` property `customerId` is referencing an `id` of a `Customer`, then both properties must always hold `ObjectID` values. If one of the property (typically `customerId`) is stored as a `string`, then LB relations stop working.

bajtos marked this conversation as resolved.
Show resolved Hide resolved
In the current version of Juggler, the interpretation of `ObjectID` field is a sub-optimal experience supported by a complex
determination process in an already complex codebase.
Expand All @@ -32,10 +33,15 @@ the consumers, and makes development and maintenance a more pleasant experience

## Proposed Solution

"Do not interpret any property not set with `mongodb: {dataType: 'ObjectID'}` as an `ObjectID`. Use string values for `ObjectID`
in public APIs and manage the coercion processes for the user."
Database-specific types like `ObjectID` and `Decimal128` should be considered as an implementation detail of a database connector.

Values of these types must not leak from the connector to Juggler and user code, code outside the connector should see a database-agnostic type like a `string`. The connector must always convert incoming values (property values, filtering queries) from database-agnostic type to database-specific type on input, and convert database-specific types back to database-agnostic type on output.

Specifically for `ObjectID`:
- Properties that should be stored as `ObjectID` in MongoDB must be defined as `{type: 'string', mongodb: {dataType: 'ObjectID'}}`.
- There will be no auto-magic coercion from `string` to `Object` for other properties (those defined without `dataType: 'ObjectID'`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- There will be no auto-magic coercion from `string` to `Object` for other properties (those defined without `dataType: 'ObjectID'`).
- There will be no auto-magic coercion from `string` to `ObjectID` for other properties (those defined without `dataType: 'ObjectID'`).


That sums up the proposed solution. Users will no longer have to deal with `ObjectID` anywhere in their experience with
Users will no longer have to deal with `ObjectID` anywhere in their experience with
LoopBack/Juggler except only in one location - the model file.

## Approaches
Expand Down Expand Up @@ -68,7 +74,7 @@ we will end up with a really huge list.
### 2. mongodb: {dataType: 'objectID'}

Setting a property to `mongodb: {dataType: 'ObjectID'}`, as it is already being done, is the better approach for marking the
property as an `ObjectID`.
property as an `ObjectID`. The same approach is also used for `Decimal128` - `mongodb: {dataType: 'decimal128'}`.

## Proof of concept

Expand All @@ -87,6 +93,12 @@ All changes are limited to `loopback-connetor-mongodb` only, Juggler is not affe
- Remove or refactor all helper functions and properties like `typeIsObjectId()`, `strictObjectIDCoercion` etc., related to previous behavior of `ObjectId`.
- There are some pieces of code that can be refactored, which involves the new changes. I think we should refactor it now now, than accumulate tech debt.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to refactor and clean up related code.

IMO, we should find a way how to unify the (more recent) implementation of Decimal128 coercion with the pre-historic coercion of ObjectID.

From what I remember, I was guiding the implementation of Decimal128 coercion to introduce helpers that can be used for other data types like ObjectID too, for example visitAllProperties and hasDataType. I think we should check how far we can get with reusing those helpers for ObjectID, and them make the necessary improvements to fix them to support any edge cases that don't work.

Also eventually, I would like to make some of these helpers database-agnostic and move them to loo pback-connector, so that we can start using them in other connectors too.



## Notes

- The changes will break compatibility with LB 3.x. Which is fine, we just need to clearly document it and remove `juggler@3` from the test suite.
- Add a "Long Term Support" section to README (see [strongloop/loopback](https://github.com/strongloop/loopback#module-long-term-support-policy) for inspiration) and also explain which connector versions are compatible with which LoopBack versions.

## Follow-up Tasks

1. Implement the functionality as proposed in - [Implementation Proposal](#implementation).