loopbackio / loopbackio/loopback-next

New syntax for INDEX and FOREIGN KEY definition

Open
#2,766 1 comment 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature Repository
Dominant language
TypeScript
Stars
5.1k
Forks
1.1k
Avg merge
2d 21h
Merged PRs (30d)
27

Description

_This is a follow-up task for the proposal outlined in https://github.com/strongloop/loopback-next/issues/2712._

**Indexes at property level**

Support the following two short-hand forms only. Ask users to use model-level
form to define indexes that are more complex.

- a "plain" index with no special configuration

```ts
@property({
type: 'string',
index: true,
})
email: string;
```

- UNIQUE index with no special configuration

```ts
@property({
type: 'string',
unique: true,
})
email: string;
```

**Indexes at model level**

At high-level, keep the current syntax where indexes are defined via a key-value
map stored in `settings.indexes` property, the key is the index name and the
value is an index definition object.

```ts
@model({
strict: false,
forceID: true,
indexes: {
uniqueEmail: {
// index definition
},
nameQueries: {
// index definition
},
},
})
class MyModel extends Entity {}
```

Individual indexes can be defined as follows:

- Add a new field `properties` as a key-value map from property names to
indexing order:

```js
// definition of an individual index
emailIndex: {
properties: {
email: 1, // ASC
createdAt: 'DESC', // alias for -1
bio: 'text', // database-specific value (MongoDB's "text")
}
}
```

Important: property names are mapped to database column names when building
the index definition.

- Keep supporting `keys` field as a key-value map from database column name to
indexing order, see the description of the actual status below. Entries from
`keys` should be merged with entries from `properties`, `keys` taking
precedence (replacing `properties` entries).

- Keep supporting `unique` field (set it to `true` to let the index enforce
uniqueness).

- Database-specific options will be stored under a key with the connector name:

```js
emailIndex: {
properties: {
email: 'ASC',
},
mongodb: {
sparse: true,
},
mysql: {
kind: 'fulltext',
type: 'hash',
},
postgresql: {
type: 'hash',
}
}
```

**Foreign keys at property level**

Introduce a new property metadata "references" (inspired by ANSI SQL):

```ts
@property({
type: 'number',
required: true,
references: {
// a TypeResolver
model: () => Category,

// name of the target property
property: 'id',

// referential actions (optional)
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
}
})
categoryId: number;
```

**Foreign keys at model level**

Modify the current connector-dependant syntax to make it easier to read and
support composite foreign keys too.

```ts
@model({
foreignKeys: {
[keyName]: {
// optional, overrides keyName
name: 'constraint_name_for_db',

// Property name(s) (will be mapped to column name)
// formerly: foreignKey
sourceProperties: ['source property name'],

// formerly: entity
targetModel: 'TargetModel',

// Property name(s) (will be mapped to column name)
// formerly: entityKey
targetProperties: ['target property name'],

// referential actions (optional)
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
},
},
})
class MyModel extends Entity {}
```

## Acceptance criteria

- [ ] Describe the new syntax in definition interfaces in model.ts (see the [spike proposal](https://github.com/strongloop/loopback-next/pull/2712/files#diff-19d587a68f35dd7b994be40da04e505b) for inspiration), include comprehensive API documentation. Make it clear that this new syntax is a work in progress and may not be supported by all connectors yet. Add links to relevant GitHub issues where people can track progress.

- [ ] Modify `DefaultCrudRepository` constructor to process model-level indexes and foreign keys; it needs to fill the corresponding fields in juggler model and property settings. The actual index/fk definitions should be passed to juggler mostly as-is.

- [ ] Update [examples/todo-list](https://github.com/strongloop/loopback-next/tree/master/examples/todo-list) to define FK and UNIQUE constraints to support existing relation definitions.

- [ ] Update [loopback4-example-shopping](https://github.com/strongloop/loopback4-example-shopping) to define FK and UNIQUE constraints to support existing relation definitions

- [ ] Update CLI templates for relations to define the constraints too. If the pull request #2426 is not landed yet then create a follow-up story instead.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the definition interfaces in model.ts and the linked spike proposal, then trace DefaultCrudRepository's constructor. Review the todo-list and loopback4-example-shopping updates and the CLI relation templates. Done means the documented syntax, repository processing, examples, and applicable template changes meet all listed acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
18/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.