복붙노트

[SQL] PostgreSQL을 / NodeJS와 결과의 배열로 테이블을 가입하세요

SQL

PostgreSQL을 / NodeJS와 결과의 배열로 테이블을 가입하세요

나는 사용자가 질문을 만들 수있는 응용 프로그램을 만드는거야, 그리고 다른 사람을 downvote / 찬성 투표 할 수 있습니다.

다음은 내 SQL 스키마의 일부입니다 :

CREATE TABLE "questions" (
  id            SERIAL,
  content       VARCHAR(511) NOT NULL,
  created_at    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
  CONSTRAINT    pk_question PRIMARY KEY (id)
);

CREATE TABLE "votes" (
  id            SERIAL,
  value         INT,
  question_id   INT NOT NULL,
  CONSTRAINT    pk_vote PRIMARY KEY (id),
  CONSTRAINT    fk_question_votes FOREIGN KEY (question_id) REFERENCES questions (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE
);

내가하고 싶은 것은 그런 투표의 배열로 나에게 각 질문을주고 포스트 그레스입니다 :

[{ // a question
  id: 1,
  content: 'huh?',
  votes: [{ // a vote
    id: 1,
    value: 1
  }, { // another vote
    id: 2,
    value: -1
  }]
}, { /*another question with votes*/ }]

나는 집계 함수 (array_agg 같은 ())에서 보았다 그러나 그것은 나에게 값만했다. A는 나에게 투표와 결합 질문을했다 JOIN, 내가하지 선호하는 서버 측 작업을 할 저를 강요한다.

그렇게 할 수있는 방법이 있습니까? 나의 추론은 내가 잘못을 얻기 위해 원하는 관련되어 있습니까?

시간 내 줘서 고마워.

해결법

  1. ==============================

    1.이 PG-약속을 쉽게 수행 할 수 있습니다 :

    이 PG-약속을 쉽게 수행 할 수 있습니다 :

    function buildTree(t) {
        return t.map('SELECT * FROM questions', [], q => {
            return t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id)
                .then(votes => {
                    q.votes = votes;
                    return q;
                });
        }).then(t.batch); // settles the array of generated promises
    }
    
    db.task(buildTree)
        .then(data => {
            console.log(data); // your data tree
        })
        .catch(error => {
            console.log(error);
        });
    

    API :지도, 어떤, 작업 배치

    관련 질문 :

    그리고 당신은 다음 PostgreSQL의 9.4 사용하고 나중에 구문을 사용하면 다음을 수행 할 수 있습니다 단지 하나의 쿼리를 사용하려면 :

    SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
        (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
         FROM votes v WHERE q.id = v.question_id))
    FROM questions q
    

    그리고 다음 페이지-약속의 예는 다음과 같습니다

    const query =
        `SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
            (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
             FROM votes v WHERE q.id = v.question_id)) json
        FROM questions q`;
    
    db.map(query, [], a => a.json)
        .then(data => {
            console.log(data); // your data tree
        })
        .catch(error => {
            console.log(error);
        });
    

    그리고 당신은 확실히 외부 SQL 파일에 복잡한 쿼리를 유지하기를 원할 것입니다. 쿼리 파일을 참조하십시오.

    위에서 제시된 접근 방법 둘 사이의 선택은 응용 프로그램의 성능 요구 사항을 기반으로해야합니다 :

    최신 정보

    부모 결과 PG-약속을 중첩 루프 쿼리를 결합 : 훨씬 향상된 성능을 제공합니다 아이 쿼리를 연결하여 다음과 같은 관련 답변을 제공 더 많은 옵션.

  2. ==============================

    2.간단한 방법을 생각하세요, 내가 맞다 될 수 있습니다, 나는 knex JS를 사용

    간단한 방법을 생각하세요, 내가 맞다 될 수 있습니다, 나는 knex JS를 사용

     let allpost = knex
            .select([
                'questions.id',
                'question.content',
                knex.raw('json_agg(v.*) as votes')
            ])
            .from('questions')
            .leftJoin('votes as v', 'questions.id', 'v.question_id')
            .groupBy('questions.id');
    
  3. ==============================

    3.SQL-툴킷은 정확히이 일을합니다. 그것은 당신이 정기적으로 네이티브 SQL을 작성하고 다시 제대로 하나가 쿼리를 분할 또는 json_build_object으로 재 작성하지 않고, (중첩) 순수 비즈니스 오브젝트를 구성받을 수 있습니다 PG-약속을 위해 만들어진 노드 라이브러리입니다.

    SQL-툴킷은 정확히이 일을합니다. 그것은 당신이 정기적으로 네이티브 SQL을 작성하고 다시 제대로 하나가 쿼리를 분할 또는 json_build_object으로 재 작성하지 않고, (중첩) 순수 비즈니스 오브젝트를 구성받을 수 있습니다 PG-약속을 위해 만들어진 노드 라이브러리입니다.

    예를 들면 :

    class Article extends BaseDAO {
      getBySlug(slug) {
        const query = `
          SELECT
            ${Article.getSQLSelectClause()},
            ${Person.getSQLSelectClause()},
            ${ArticleTag.getSQLSelectClause()},
            ${Tag.getSQLSelectClause()}
          FROM article
          JOIN person
            ON article.author_id = person.id
          LEFT JOIN article_tags
            ON article.id = article_tags.article_id
          LEFT JOIN tag
            ON article_tags.tag_id = tag.id
          WHERE article.slug = $(slug);
      `;
      return this.one(query, { slug });
      // OUTPUT: Article {person: Person, tags: Tags[Tag, Tag, Tag]}
    }
    

    select 절은 아니라 이름없는 충돌을 (아무것도 마법이 일어나고, 그냥 대신 기입 할 수 있습니다) 보장하지 않기 때문에, 열을 입력에서 지루함을 저장 "getSQLSelectClause"방법 비즈니스 개체를 사용합니다.

    this.one는 SQL-툴킷 기본 DAO 클래스로 호출입니다. 그것은 좋은 중첩 된 구조로 평면 결과 레코드 구조에 대한 책임이 있습니다.

    . (또한 통지는 하나, oneOrNone, 많은에 대한 DAO의 메소드 SQL에 대한 우리의 정신 모델과 일치 "하나"이며, 모든 생성 최고 수준의 비즈니스 오브젝트의 수에 대해 자신의 수를 확인하는 것이 -는 SQL없는 행의 수를 표현 반환!)

    PG-약속의 상단에를 설정하는 방법에 대한 자세한 내용은 저장소를 확인하십시오. 그것은 엄격하게 강화, 그리고 추상적 인 아웃 PG-약속 (당신은 여전히 ​​PG-약속을 설정하고 직접 사용할 수 있습니다)을 추구하지 않습니다. (Disclamer, 나는 SQL-툴킷의 저자입니다.)

  4. from https://stackoverflow.com/questions/39805736/get-join-table-as-array-of-results-with-postgresql-nodejs by cc-by-sa and MIT license