Skip to content

Can't find entities by their composite keys #1205

@edusperoni

Description

@edusperoni

Environment

------------------------------
- Operating System: Linux
- Node Version:     v16.14.2
- Nuxt Version:     3.4.2
- Nitro Version:    2.3.3
- Package Manager:  npm@7.17.0
- Builder:          vite
- User Config:      -
- Runtime Modules:  -
- Build Modules:    -
------------------------------

Reproduction

https://stackblitz.com/edit/github-6qqdqu?file=app.vue,tsconfig.json

Describe the bug

When creating an entity with a composite primary key, it's impossible to find this entity by its key anymore.

Ideally this could be used to speedup the lookup process of some entities.

If you do repo.find('[id1,id2]'), it does find the correct ids in the first steps (storeFind), but will fail the where condition on the 2nd step (filterWhere). Shouldn't the id where be removed from the wheres clauses since it's already fulfilled in storeFind?

Additional context

I have an User, Community, and CommunityProfile. By using [community_id, user_id] I can quickly fetch the desired profile when I know both of them (which is almost always in my scenario).

Additionally, while digging through the code, I found that storeFind iterates over all the store entities looking for a specific id. Is this done intentionally? Wouldn't it be faster to iterate over the desired ids and check if they're on the store? Using an array there also seems slow:

Current implementation:

  protected storeFind(ids: string[] = []): Collection<M> {
    const data = this.commit('all')
    const collection = [] as Collection<M>

    for (const id in data) {
      if (ids === undefined || ids.length === 0 || ids.includes(id))
        collection.push(this.hydrate(data[id], { visible: this.visible, hidden: this.hidden, operation: 'get' }))
    }

    return collection
  }

Alternative implementation 1 (single object lookup per id, much faster than iterating over all entities):

  protected storeFind(ids: string[] = []): Collection<M> {
    const data = this.commit('all')
    const collection = [] as Collection<M>
    const deduplicatedIds = new Set(ids && ids.length ? ids : [])
    deduplicatedIds.forEach((id) => {
        if (id in data)
            collection.push(this.hydrate(data[id], { visible: this.visible, hidden: this.hidden, operation: 'get' }))
    })

    return collection
  }

Alternative implementation 2 (preserve data order, a bit faster)

  protected storeFind(ids: string[] = []): Collection<M> {
    const data = this.commit('all')
    const collection = [] as Collection<M>
    const deduplicatedIds = new Set(ids && ids.length ? ids : [])
    for (const id in data) {
      if (deduplicatedIds.has(id))
        collection.push(this.hydrate(data[id], { visible: this.visible, hidden: this.hidden, operation: 'get' }))
    }

    return collection
  }

Logs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions