Using TypeORM's QueryBuilder to select a random record with a nested relation

Imagine a scenario where I have the following entities:

User

@Entity('user', { synchronize: true })
export class UserEntity {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @OneToMany(type => PostEntity, post => post.user)
  posts: PostEntity[];

}

Post

@Entity('post', { synchronize: true })
export class PostEntity {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToOne(type => UserEntity , user => user.posts)
  @Index()
  user: UserEntity ;

  @Column({ nullable: true })
  text: string;
}

The goal is to retrieve one random post along with its associated user, nested inside a user property within the object.

While utilizing the TypeORM repository class, this task can be achieved effortlessly:

  public async getOnePost(): Promise<PostEntity> {
    return await this.findOneOrFail({
      relations: ['user']
    });

This will provide a PostEntity object with a user property that contains a well-structured UserEntity object.

However, when it comes to fetching a random record from the database, the use of TypeORM QueryBuilder is necessary. I was able to come up with the following solution:

const array = await this.createQueryBuilder()
  .select('*')
  .from(PostEntity , 'post')
  .leftJoinAndSelect('post.user','user')
  .orderBy('RANDOM()')
  .limit(1)
  .execute();
return array[0];

After experimenting with the relation/join functions and parameters, I could only achieve:

  1. Only 1 property "userId" added to the PostEntity object
  2. "userId" property and all other user properties added in a "flat" manner to the PostEntity object
  3. "userId" property added, while all other user properties are incorporated "flat" with an alias: user_id, user_firstName, etc.

Therefore, using QueryBuilder, how can I acquire a Post structured like this:

{
  id: 'e43c918c-55e1-4511-bce4-910fdd503548',
  text: 'this is some text',
  user: {
    id: '123456789',
    firstName: 'John',
    lastName: 'Doe',
  },
}

Answer №1

While facing a similar issue with executing raw queries, I discovered a solution which involved utilizing JSONB_BUILD_OBJECT()

https://www.postgresql.org/docs/9.5/functions-json.html

The approach is to structure the query in this fashion:

select
  post.*,
  jsonb_build_object(
    'id', user."id",
    'firstName', user."firstName",
    'lastName', user."lastName"
  ) "user"
from...

I'm intrigued by the possibility of achieving this elegantly through a typeorm clause, however, my workaround for such API challenges has been resorting to raw queries.

Answer №2

I found a solution that worked perfectly for me:

import { Entity, PrimaryGeneratedColumn, Column, Unique} from 'typeorm';

@Entity({ name: 'users' })
@Unique(['email'])
export class User {
  @PrimaryGeneratedColumn()
  id: number;
  ...
}
const userRepository = myDataSource.getRepository(User);
const randomUser = await userRepository
      .createQueryBuilder('user')
      .select()
      .orderBy('RANDOM()')
      .getOne();

I discovered this helpful tip here

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 code inside the promise .then block is executing long before the promise has completed its

After spending quite some time working on this messy code, I finally have a functioning solution: loadAvailabilities() { let promises = []; let promises2 = []; let indexi = 0; //return new Promise((resolve, reject) => { this.appo ...

Challenges encountered when passing objects with Angular 2 promises

I am encountering a problem when using a promise to retrieve a Degree object in Angular 2. The initial return statement (not commented out) in degree.service functions correctly when paired with the uncommented implementation of getDegree() in build.compon ...

Collection of assorted objects with varying sizes that are all subclasses of a common superclass

I need to create an array that can hold any number of items, all of which are subclasses of the same base class. The issue I'm facing is with type checking in TypeScript - when I declare the array as Array<BaseClass>, I have to cast each item to ...

Typeorm stored procedure that returns a JSON response

Whenever I execute the stored procedure defined in a Microsoft SQL database using TypeORM as shown below: const result=await conn.query('exec Spname @0,@1',[inp1val,inp2val]); I receive a response from the database, but it comes with an addition ...

Why are my animation states being shared among different instances of the component?

Why is the animation playing for both instances of the carousel component when interacting with just one call (e.g. clicking next or prev)? carousel.component.ts @Component({ selector: 'app-carousel', standalone: true, templateUrl: './c ...

Using Vuetify to filter items in a v-data-table upon clicking a button

My table structure is similar to this, I am looking to implement a functionality where clicking on the Filter Button will filter out all items that are both male and valid with a value of true. users = [ { name: 'ali', male: true, valid: ...

What is the way to assign a variable to ngClass in Angular?

I'm currently working on creating modals that will display different content based on which button is clicked. Each button should trigger a unique modal to appear, each with its own specific content inside. When a button is clicked, the 'active&a ...

You are unable to call upon an object that may be of type 'undefined' in typescript

Among all the other inquiries on this topic, my issue lies with the typescript compiler seeming perplexed due to the following code snippet: if(typeof this[method] === "function"){ await this[method](req,res,next) } The error message I am en ...

Tips for updating the checkbox state while iterating through the state data

In my component, I have the ability to select multiple checkboxes. When a checkbox is selected, a corresponding chip is generated to visually represent the selection. Each chip has a remove handler that should unselect the checkbox it represents. However, ...

Tips for obtaining the "inner type" of a particular "instance" in TypeScript's generics

Unable to find more appropriate language to elaborate beyond the title, I'm going to rely on the code itself: let var1 = someExternalLibraryMethod(); // assume var1 is implicitly Promise<string> let var2: typeof var1; // this approach enables ...

What is the best way to show an error message if a TextInput field is left blank?

I'm currently working on a mobile application using react-native, focusing on the login page. My goal is to show an error message below a TextInput field when it's left empty. To achieve this, I've been experimenting with the @react-hook-f ...

The variable is currently undefined because it has an array assigned to it

Upon selecting multiple checkboxes for variants, I am retrieving checked data using the following method: get selectedIdsFromViolCategoriesFormArray(): string[] { return this.violCategories .filter((cat, catIdx) => this.violCategoriesFormArr. ...

Tips for implementing lazy loading for a section of a template in Angular 2

I have an Angular 2 component that has several sub-components within it. Some of these sub-components are expensive to load and may not always be necessary, especially if the user doesn't scroll far enough down the page. Although I am familiar with l ...

Could it be possible for a Firestore onUpdate trigger's change parameter, specifically change.after.data() and change.before.data(), to become null or undefined?

Presented below is a snippet of my cloud function exports.onUpdateEvent = functions.firestore.document('collection/{documentId}') .onUpdate((change, context) => { const after: FirebaseFirestore.DocumentData = change.after.data(); const ...

How can we optimize component loading in react-virtualized using asynchronous methods?

In my component, I have implemented a react-virtualized masonry grid like this: const MasonrySubmissionRender = (media: InputProps) => { function cellRenderer({ index, key, parent, style }: MasonryCellProps) { //const size = (media.submiss ...

Typescript's Approach to Currying

In TypeScript, I am attempting to define types for a currying function. The implementation in JavaScript is shown below: function curry1(fn) { return (x) => (fn.length === 1 ? fn(x) : curry1(fn.bind(undefined, x))); } This function works effectively ...

Guide on specifying the return type of a generic class when using TypeScript

The code I am working with is structured like this: import * as events from 'events' // Utilizing Node.js events module // My custom implementation of EventEmitter with enhanced typing interface IEventEmitter<EventTypes> { /* ... */ } // ...

Storing Angular header values in local storage

saveStudentDetails(values) { const studentData = {}; studentData['id'] = values.id; studentData['password'] = values.password; this.crudService.loginstudent(studentData).subscribe(result => { // Here should be the val ...

How is it possible to receive a TRUE value when the API returns an error message indicating that the requested photo does not exist?

I am currently in the process of learning Angular and Typescript, but I am facing some challenges. I am working on an application that involves displaying a list of photos, as well as allowing users to create, edit, and delete existing photos. However, whe ...

Data fetched using React Query

When using React Query to fetch data, the function runs smoothly. After console.logging the 'data' variable from React Query, it prints an array of objects as expected and handles states efficiently between loading, success, error. The issue ar ...