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

Collection populate with references #1158

Closed
Wolvereness opened this issue Dec 3, 2020 · 5 comments
Closed

Collection populate with references #1158

Wolvereness opened this issue Dec 3, 2020 · 5 comments
Labels
enhancement New feature or request
Milestone

Comments

@Wolvereness
Copy link

Is your feature request related to a problem? Please describe.
When working with a ManyToMany relationship, I only need the primary-key of the corresponding entity. All methods of populating the Collection yields the corresponding entities fully populated.

Describe the solution you'd like
A method that only accesses the relationship table to make uninitialized references in the Collection.

Describe alternatives you've considered
Fully populating the entities works, but it's much more data than the problem requires.

Additional context
Joining the relationship-table can produce a lot of data in quadratic big-O, and double-select increases the request latency.

@Wolvereness Wolvereness added the enhancement New feature or request label Dec 3, 2020
@B4nan
Copy link
Member

B4nan commented Mar 21, 2021

It's worth noting that there is actually only one query that loads both the pivot table and joins the target table (also in the select in strategy). There will always be entities - references are still entities. The only things that we can skip by doing this is the join and hydration of target entities. Of course for large collections this can be worth it.

I will also add that in v4 it is possible to add to an uninitialized collection.

Here is a proposed API for this:

await book.tags.init({ reference: true });
await em.populate(book, ['tags:ref']);
await em.find(Book, { ... }, ['tags:ref']);
// might use something else than `LoadStrategy`, not sure now
await em.find(Book, { ... }, { populate: { tags: LoadStrategy.REFERENCE } });

@olivierlacan
Copy link

@B4nan This is exactly what we were looking for. We'd love to be able to just init the join/pivot table primary key(s).

If you need any help bringing this feature up or testing it, lmk. 😃

@B4nan
Copy link
Member

B4nan commented Jan 15, 2022

I guess the biggest issue right now might be the proposed API, as populate hints are now (v5) string arrays only and they are strictly typed, so we would need to adjust that part to support things like ['tags:ref'] (already tried some time ago, it seemed harder than anticipated) or come up with a different way to pass this information (which would itself be probably a lot of work to support). The implementation itself might be rather easy.

@B4nan B4nan added this to the 6.0 milestone Sep 30, 2023
B4nan added a commit that referenced this issue Oct 2, 2023
Sometimes we might want to know only what items are part of a collection, and we don't care about the values of those items. For this, we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Oct 2, 2023
Sometimes we might want to know only what items are part of a collection, and we don't care about the values of those items. For this, we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Oct 2, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
@B4nan
Copy link
Member

B4nan commented Oct 2, 2023

Implemented in v6 via #4776

@B4nan B4nan closed this as completed Oct 2, 2023
@Wolvereness
Copy link
Author

Awesome! Looking forward to our v6 upgrade.

B4nan added a commit that referenced this issue Oct 2, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Oct 17, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Oct 21, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Oct 25, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Nov 2, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
B4nan added a commit that referenced this issue Nov 5, 2023
Sometimes we might want to know only what items are part of a
collection, and we don't care about the values of those items. For this,
we can populate the collection only with references:

```ts
const book1 = await em.findOne(Book, 1, { populate: ['tags:ref'] });
console.log(book1.tags.isInitialized()); // true
console.log(wrap(book1.tags[0]).isInitialized()); // false

// or alternatively use `init({ ref: true })`
const book2 = await em.findOne(Book, 1);
await book2.tags.init({ ref: true });
console.log(book2.tags.isInitialized()); // true
console.log(wrap(book2.tags[0]).isInitialized()); // false
```

Closes #1158
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants