如何构造涉及多个表的查询?

时间:2019-05-11 01:42:21

标签: javascript sql node.js postgresql postgresql-9.1

我正在尝试构建一个查询以在“关注”表中查找用户的关注者, 然后在“ userCategories”表中查看每个关注者最喜欢的类别, 然后在这些类别中寻找问题, 然后分别在“问题”,“答案”或“评论”表及其类别中查找他们提出,回答或评论过的问题, 然后,查找这些类别中的所有问题, 然后返回所有问题。 有可能吗?

我的表格-

CREATE TABLE follow (
  "followingUserId" INTEGER REFERENCES account(id),
  "followedUserId" INTEGER REFERENCES account(id)
);

CREATE TABLE userCategory (
  "accountId" INTEGER REFERENCES account(id),
  "categoryId" INTEGER REFERENCES category(id),
  PRIMARY KEY ("accountId", "categoryId")
);

CREATE TABLE question (
  id                              SERIAL PRIMARY KEY,
  body                            TEXT,
  "accountId"                     INTEGER,
  "categoryId"                    INTEGER,
  token                           TSVECTOR,
  FOREIGN KEY ("accountId")       REFERENCES account(id),
  FOREIGN KEY ("categoryId")      REFERENCES category(id)
);

CREATE TABLE answer (
  id                            SERIAL PRIMARY KEY,
  body                          TEXT,
  "questionId"                  INTEGER,
  "accountId"                   INTEGER,
  FOREIGN KEY ("questionId")    REFERENCES question(id),
  FOREIGN KEY ("accountId")     REFERENCES account(id)
);

CREATE TABLE comment (
  id                           SERIAL PRIMARY KEY,
  body                         TEXT,
  "accountId"                  INTEGER,
  "questionId"                 INTEGER,
  "answerId"                   INTEGER,
  FOREIGN KEY ("accountId")    REFERENCES account(id),
  FOREIGN KEY ("questionId")   REFERENCES question(id),
  FOREIGN KEY ("answerId")     REFERENCES answer(id)
)

目前,我能够通过单独的查询和一些链接的Promises返回用户及其关注者最喜欢的类别中的问题。可以想象,随着我深入到Promise链中,这一过程变得越来越复杂。以性能为代价,我确定我当前的方法是可怕的。

这就是我在做atm-

//recommended questions for users based on their categories
    static getRecommendedQsByCates({ accountId }) {
        return new Promise((resolve, reject) => {
            pool.query(
                `SELECT id, body, question."categoryId", question."accountId" FROM question INNER JOIN userCategory
         ON question."categoryId"=userCategory."categoryId"
         WHERE userCategory."accountId"=$1`,
                [accountId],
                (err, res) => {
                    if (err) return reject(err)
                    resolve({ questions: res.rows })
                }
            )
        })
    }


//recommended-questions route based on users liked categories, 
//and the categories liked by the people user follows.

    //get users liked categories, and the questions in those categories
    //push them into a queue.
    //if no categories exists, then return all questions
    //then, find the categories liked by all the followed users
    //find questions belonging to those categories
    //push those questions into the queue
    //remove duplicates questions
    //return one final array


router.get(
    '/questions',
    passport.authenticate('jwt', { session: false }),
    (req, res, next) => {
        const { id } = req.user
        let aggregateRecommendedQuestions = []
        let dupsRemoved = []
        Question.getRecommendedQsByCates({ accountId: id })
            .then(({ questions }) => {
                if (questions && questions.length > 0) {
                    questions.map(question => aggregateRecommendedQs.push(question))
                } else {

                    Question.getAllQuestions().then(({ questions }) => {
                        if (questions && questions.length > 0) {
                            res.json({
                                type: 'FOUND',
                                message: 'All questions',
                                questions: questions
                            })
                        } else {
                            res.json({
                                type: 'NO_QUESTIONS',
                                message:
                                    'No question has been asked yet. Be the first to ask a meaningful question.'
                            })
                        }
                    }).catch(err => next(err))
                }
            })
            .then(() => {

                Follow.findFollowed({ accountId: id }).then(resp => {
                    resp.map(({ followed }) => {
                        Promise.all([
                            UserCategory.getUserCategories({ accountId: followed })
                        ]).then(resp => {
                            resp.map(({ categories }) => {
                                // console.log(categories)
                                categories.map(({ categoryId }) => {
                                    Promise.all([Question.getQuestionsByCategory({ categoryId })])
                                        .then(resp => {
                                            resp.map(({ questions }) => {
                                                aggregateRecommendedQs.push(questions[0])
                                            })
                                        })
                                        .then(() => {
                                            //remove duplicates
                                            dupsRemoved = Object.values(
                                                aggregateRecommendedQs.reduce(
                                                    (acc, curr) => ((acc[`${curr.body}`] = curr), acc),
                                                    {}
                                                )
                                            )
                                        })
                                })
                            })
                        })
                    })
                })
            })
            .catch(err => next(err))
        setTimeout(() => {
            res.json({
                type: 'FOUND',
                message:
                    'Here are some questions based on the users and his/hers followed users categories',
                questions: dupsRemoved
            })
        }, 100)
    }
)

所有这些之后,我什至还没有研究所有答案中的“ questionId”以及针对关注者的注释表。 这目前正在起作用,但我需要一种更好的方法来查找所有问题。

是否可以构造一个执行全部或至少使我关闭而不执行所有promise的sql查询?

0 个答案:

没有答案