Как я могу построить запрос, включающий несколько таблиц? - PullRequest
0 голосов
/ 11 мая 2019

Я пытаюсь составить запрос, чтобы найти подписчиков пользователя в таблице «Follow», затем просмотреть любимые категории каждого подписчика в таблице «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)
)

В настоящее время я могу отвечать на вопросы из любимых категорий пользователей и его / ее подписчиков с отдельными запросами и некоторыми связанными обещаниями.Как вы можете себе представить, это становится все более и более сложным, когда я углубляюсь в цепочки 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" в ответе и таблицы комментариев дляпоследователи.Пока это работает, но мне нужен лучший способ найти все вопросы.

Можно ли построить SQL-запрос, который делает все это или, по крайней мере, приблизить меня, не выполняя все обещания?

...