ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 노드 관계 쿼리
    노드 2023. 4. 18. 14:07

    *시퀄라이저를 사용하고 있는 환경에서

     

    관계 쿼리는 결괏값이 자바스크립트 객체이다.

     

    만약에 사용자를 가져온다~ 라고 하면 다음과 같다

    const user = await User.findOne({}); //모두 가져올거면 findAll
    console.log(user.nick); //사용자 닉네임

    user에 유저 한 명을 찾아서 할당을 했고 출력문을 통해 그 유저의 닉네임에 접근했다. 결괏값이 자바스크립트 객체여서 가능한 일이다.

     

    include로 JOIN 과 비슷한 기능 수행 가능(관계 있는 것 엮을 수 있음)

     

    만약에 내가 쓴 댓글까지 가져오고 싶다면 어떻게 할까?

    SQL에서는 조인을 사용해야 하지만 시퀄라이저에서는 User.findOne 한 다음에 include에 Coomment를 넣어주면 된다.

    const user = await User.findOne({
      include: [{
        model: Comment,
      }]
    });
    console.log(user.Comments); //사용자 댓글

    사용자를 가져오면서 그 사용자가 작성했던 댓글까지 함께 가져온다. 

    출력문에서는 Comments로 복수형이 쓰였는데 그 이유는 hasMany이기 때문이다. hasOne이면 Comment로 자동으로 바뀌게 된다. 

    시퀄라이저가 어떤 관계형인지에 따라서 자동으로 변환해 준다. 

     

    다대다 모델은 다음과 같이 접근이 가능하다

    db.sequelize.models.PostHashtag

     

    get+모델명으로 관계 있는 데이터 로딩 가능

    const user = await User.findOne({});
    const comments = await user.getComments();
    console.log(comments); //사용자 댓글

    유저를 가지고 와서 getComments()를 하면 그 사용자가 작성했던 모든 댓글들을 다 가지고 올 수 있다. 위에서 include하는 방법과는 또 다른 방식으로 가지고 온 것이다. 

    *단, include를 사용하면 성능상 문제가 생길 수 있다. 이유는 동시에 가져오는 것이기 때문에 db가 좀 더 일을 많이 해야하기 때문이다.

     

    as로 모델명 변경 가능

    //관계를 설정할 때 as로 등록
    db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id', as: 'Answers'});
    
    //쿼리할 때는
    const user = await User.findOne({});
    const comments = await user.getAnswers();
    console.log(comments); //사용자 댓글

    만약에 getComments(), 또는 user.Comments 부분을 좀 바꾸고 싶다~ 하면 as로 바꿀 수 있다. 

    as를 써서 getAnswers() 로 바뀐 것을 볼 수 있다. 

    *include를 사용해도 마찬가지이다. 다만, 모델을 기입하는 자리에는 실제 모델의 명이 와야한다.

    const user = await User.findOne({
      include: [{
        model: Comment,
      }]
    });
    console.log(user.Answers); //사용자 댓글

    실제로 가져올 때만 실제하는 모델명을 사용하고 출력할때만 as로 바꾼 부분으로 출력한다.

    *오히려 햇갈릴 수 있으니 자주 쓰는 것은 별로 추천하지 않는다. 

     

    include나 관계 쿼리 메서드에도 where나 attributes 사용 가능하다

     

    const user = await User.findOne({
      include: [{
        model: Comment,
        where: {
          id: 1,
        },
        attributes: [id],
      }]
    });
    
    //또는
    const comments = await user.getComments({
      where: {
        id: 1,
      },
      attributes: ['id'],
    });

    여기서 where는 댓글에서의 where이다. 

    어떤 사용자의 댓글을 가져오는데 댓글의 id가 1인 것만 가져와라~ 하는 코드이다. 

    *어떤 사람의 댓글을 가져오는데 그 사용자의 id가 1이어야 한다~ 와는 매우 다른 것이기 때문에 where절이 어디에 적용되는지가 매우 중요하다. 이것을 원할 경우 include 밖에다 where을 써 주면 된다. 

     

    attributes는 댓글에 속성이 여러 개 있을 수 있는데 그 중 id만 가지고 오겠다~ 라는 뜻이다.

    만약 사용자의 아이디만 가지고 오고 싶으면 include 밖에서 attributes를 사용하면 된다. 

     

    생성 쿼리

    const user = await User.findOne({});
    const comment = await Comment.create();
    await user.addComment(comment);
    //또는
    await user.addComment(comment.id);

    사용자를 먼저 만들고 빈 댓글을 만들었다.

    이후에 add를 이용해서 user에 댓글을 할당했다. 

    이렇게 하면 사용자와 댓글하고 연결이 되서 저장이 된다. 

     

    여러 개를 추가할 때는 배열로 추가 가능

    const user = await User.findOne({});
    const comment1 = await Comment.create();
    const comment2 = await Comment.create();
    await user.addComment([comment1, comment2]);

    배열로 여러 개를 추가한다.

     

    수정은 set+모델명, 삭제는 remove+모델명이다. 

    원래 쿼리에서는

    create

    find

    update

    destroy

     

    관계 쿼리에서는

    add

    get

    set

    remove

     

    단어들이 조금 다른 것을 볼 수 있다. 

    관계 쿼리와 일반 쿼리의 동사명이 조금 다르다~ 라는 점을 알고 넘어가자

     

    raw 쿼리

    직접 SQL을 쓸 수 있다.

    const [result, metadata] = await sequelize.query('SELECT * FROM comments');
    console.log(result);

    raw쿼리를 이용하면 직접 위와 같은 방법으로 SQL을 직접 쓸 수 있다. 

    '노드' 카테고리의 다른 글

    노드 데이터베이스 CRUD 작업하기  (0) 2023.04.18
    노드 데이터베이스 MySQL  (1) 2023.04.18
    노드 테이블 관계 이해하기  (0) 2023.04.18
    노드 next 활용법  (0) 2023.04.17
    노드 미들웨어 특성 이해하기  (0) 2023.04.17
Designed by Tistory.