How can TypeORM be used to query a ManyToMany relationship with a string array input in order to locate entities in which all specified strings must be present in the related entity's column?

In my application, I have a User entity that is related to a Profile entity in a OneToOne relationship, and the Profile entity has a ManyToMany relationship with a Category entity.

// user.entity.ts

@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @OneToOne(() => Profile, {
    cascade: true,
    nullable: true,
  })
  @JoinColumn() // user owns the relationship (User table contains profileId). Use it only on one side of the relationship
  profile: Profile;
}
// profile.entity.ts

@Entity()
export class Profile {
  @PrimaryGeneratedColumn('uuid')
  id: number;

  @OneToOne(() => User, (user: User) => user.profile)
  user: User;

  @ManyToMany(() => Category, (category: Category) => category, {
    cascade: true,
    nullable: true,
  })
  @JoinTable()
  categories: Category[];
}
// category.entity.ts

@Entity()
export class Category {
  @PrimaryGeneratedColumn('uuid')
  id: number;

  @Column()
  name: string;

  @ManyToMany(() => Profile, (profile: Profile) => profile.categories, {
    nullable: true,
  })
  profiles: Profile[];
}

I am aiming to retrieve all user entities where the category names associated with the profile match those present in a given string array input e.g.

const categories = ['category1', 'category2']
. Currently, I am using the IN clause with a query builder to accomplish this goal.

The query implementation utilizing IN:

const categories = ['category1', 'category2']

const users = await this.usersRepository
  .createQueryBuilder('user')
  .innerJoinAndSelect('user.profile', 'profile')
  .innerJoinAndSelect('profile.categories', 'categories')
  .where('categories.name IN (:...categories)', {
    categories,
  })
  .getMany();

I specifically want users where both category1 AND category2 are among the names of the many to many relations of the profile. The current query also retrieves users if only one of these values is present in the names. Is there a way to achieve this within my existing structure?

A similar issue was discussed in this thread, but the entities were unrelated in that case.

Another relevant discussion can be found in this post, although it pertains to filtering based on a string array column rather than many to many relations.

I prefer to maintain my current structure as I might need to introduce additional columns to the category entity in the future, such as an ordering attribute.

Update:

To address my requirements more effectively, I have opted to use a string array instead of a many to many relation.

// profile.entity.ts

@Column('text', {
  nullable: true,
  array: true,
})
categories?: string[];

The revised query looks like this:

const categories = ['category1', 'category2']

const users = await this.usersRepository
  .createQueryBuilder('user')
  .innerJoinAndSelect('user.profile', 'profile')
  .where('profile.categories::text[] @> (:categories)::text[]', {
    categories,
  })
  .getMany();

Answer №1

For PostgreSQL users, one useful approach is to utilize the @> contains array operator.

const categories = ['category1', 'category2']

// untested code
const users = await this.usersRepository
  .createQueryBuilder('user')
  .innerJoinAndSelect('user.profile', 'profile')
  .innerJoin('profile.categories', 'categories')
  .groupBy('user.id')
  .addGroupBy('profile.id');
  .having('array_agg(categories.name::text) @> ARRAY[:...categories]', {
    categories,
  })
  .getMany();

Rather than selecting categories directly, this method aggregates the joined categories into an array and checks if it contains all elements of the given array. Although I haven't been able to test this functionality with TypeORM integration, I'm optimistic that it can handle the array-building syntax successfully despite its absence from the documentation. Hopefully, you will find this solution beneficial.

Edit: Incorporated missing groupBy and a cast operation, as suggested in previous feedback.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The app is having trouble loading in Node because it is unable to recognize jQuery

I am currently using Node to debug a JavaScript file that includes some JQuery. However, when I load the files, the $ sign is not recognized. I have installed JQuery locally using the command npm install jquery -save-dev. The result of "npm jquery -versio ...

Tips for integrating Tornado authentication with AngularJS

I have been experimenting with the authentication system outlined in the tornado documentation, and I am encountering a Cross-Origin Request issue when trying to integrate it with AngularJS. Is there a way to successfully combine Tornado's authentica ...

Getting into a dynamic named property inside another object in angular can be achieved by utilizing bracket notation

I encountered an issue in my Angular 8 project where I create an object from a JSON, but there is a dynamic property whose name is unknown until runtime. This causes problems when trying to access the value of that dynamic property within another object, l ...

Instead of displaying the name, HTML reveals the ID

I have defined a status enum with different values such as Draft, Publish, OnHold, and Completed. export enum status { Draft = 1, Publish = 2, OnHold = 3, Completed = 4 } In my TypeScript file, I set the courseStatus variable to have a de ...

Safari AJAX glitch - Unable to load requested resource

Today, an unexpected bug has appeared in a web app I'm currently developing. Without making any changes to the code, this bug suddenly emerged: I am sending AJAX requests (using vanilla JavaScript instead of jQuery) to our local server running MAMP P ...

InjectableToken missing in Angular Standalone Component - Provider Not Found

In my standalone component, I am using an Injection Token to set a path (the paths are not the same for all micro-frontends). However, I do not provide this token in the component itself because I need to override it using providers in my app-module.ts. H ...

Verify the ability to view a webpage

I am currently working on creating a method to check if data access is equal to next.data.access. Since it's an array, I cannot use the includes method. It would be enough for just one of the data access values in the array to return true. auth.guard ...

What is the best way to pass default event argument alongside another argument in React?

This snippet demonstrates the function I wish to call when a certain input type is invoked: _handleOnEnterPress = (e, receiverUserId) => { if (e.keyCode === 13) { // assuming keycode 13 corresponds to 'enter' console.log("pressed ...

Issue occurs when nested functions prevent the data() variable from updating

As a newcomer to VUE, I may not be using the right terminology so bear with me. I'm attempting to update a variable that is defined in the script tag's "data()" function. The issue arises when trying to change the value of a variable within the ...

Adonisjs latest version (v5) model creation command malfunctioning

Using Adonisjs v5 The controller command works fine with: node ace make:controller Posts However, the new model creation command is not working: node ace:make model Post When running the make model command, an error occurs: An error message stating &ap ...

Something went wrong with @wdio/runner: unable to establish session

After successfully developing cucumber tests that passed and tested some URLs with Chrome, I encountered errors when uploading to the pipeline despite the tests succeeding. Webdriver generated the following errors: INFO webdriver: DATA { 57[0-0] capabili ...

JavaScript Ping Pong Challenge

I'm currently investigating why the browser returns NaN for the Positions. The game is being rendered in a loop and updated as soon as the monitor is ready, which is defined in the update() function and runs infinitely. The reset() function is a part ...

Transferring a DOM element to a different window while preserving event listeners in Internet Explorer 11

I am tasked with creating a webpage feature that allows users to detach a section of the page and move it to a new window on a second monitor, then reattach it back to the main page. The detached section must retain its state and event listeners during the ...

Display information from a Google Sheet onto a leaflet map based on specified categories

I am currently facing some challenges while creating a map with markers using data from Google Sheet and leaflet. Despite my efforts, I have encountered a few bugs that are proving to be difficult to resolve: Group Filtering - Although I can successfully ...

Animated smooth updates in d3 line graphs are the key to creating dynamic and

I'm attempting to modify an example of Animated Line Graphs from: http://bl.ocks.org/benjchristensen/1148374 <div id="graph1" class="aGraph" style="width:600px; height:60px;"></div> <script> function draw(id, width, height, upd ...

The functioning of invoking JavaScript confirm from the code behind is experiencing issues

Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click Dim ResourceObject As Object Dim js As [String] = (vbCr & vbLf & " if(confirm('Are you sure you want to delete from th ...

Retrieving property values from an object across multiple levels based on property name

I have a complex object structure that contains price information at various levels. My goal is to retrieve all values from the Price property, regardless of their nesting within the object. var o = { Id: 1, Price: 10, Attribute: { Id: ...

Removing the @Input decorator in Angular's codebase

I am currently working on an Angular project for a class, and I'm facing an issue where removing the @Input decorator from my component is causing the entire application to not load properly. import { Component, OnInit, Input } from '@angular/ ...

Setting up Electron with React and TypeScript: A Comprehensive Guide

I've been developing an app using Electron, React (jsx), and Babel. However, I recently made the switch to TypeScript and I'm struggling to get everything functioning properly. The npm packages I've tried only work for either React or TypeSc ...

Utilizing Gulp locally without the need for global installation or referencing the bin js file

I have a gulpfile.js that runs perfectly when I type 'gulp' into the command line. Essentially, the 'gulp' bash command just calls the specific js file outlined in 'package.json >> bin >> gulp' of the globally ins ...