Получение 10 самых последних отзывов для каждого местоположения - PullRequest
0 голосов
/ 07 ноября 2019

Я пишу запрос, использую пулы в Node и Express. Что я пытаюсь сделать, получить 10 самых последних отзывов для каждого местоположения. Я пытаюсь сделать это, используя следующий код.

var returnObj = [];

router.get('/', (req, res) =>{
    const LocationsQuery = 'SELECT locationID FROM locations GROUP BY locationID';

    connection.getConnection(function(err, connection) {
        connection.beginTransaction(function(err) {
            if (err) {                  
                connection.rollback(function() {
                    connection.release();
                });
            } else {
                connection.query(LocationsQuery, function(err, results) {
                    if (err) {      
                        connection.rollback(function() {
                            connection.release();
                        });
                    }   

                    for(var i = 0; i < results.length;i++){
                        var dataQuery = `SELECT  locations.businessName, locations.address, locations.city, locations.state, locations.zipCode, locations.Country, r.comfort,
                                            r.timeliness, r.politeness, r.accessibility, r.averageRating, r.food, r.breakRoom, r.restroom
                                            FROM (SELECT reviews.locationID, reviews.comfort,  reviews.timeliness, reviews.politeness,  reviews.accessibility,
                                                    (reviews.comfort +  reviews.timeliness + reviews.politeness +  reviews.accessibility) / 4 AS averageRating, 
                                                    reviews.food, reviews.breakRoom, reviews.restroom
                                                    FROM reviews 
                                                    WHERE reviews.locationID = ${results[i].locationID}) r 
                                        LEFT JOIN locations on locations.locationID = r.locationID   
                                        LIMIT ${config.limit}`

                        connection.query(dataQuery,function(err, res) {

                            if (err) {      
                                connection.rollback(function() {
                                    connection.release();
                                });
                            } 

                            //Get the Averages of the ratings then creates 
                            // Json Object out of the MYSQL return Data 
                            object = setup(res)
                            returnObj.append(object)
                            console.log(object)
                        });
                    } //End For loop
                });
            }    
        });
    });
    res.send(returnObj);
});

Проблема, с которой я сталкиваюсь, заключается в выполнении n + 1 запросов к базе данных. (Один, чтобы получить все местоположения, и n, чтобы пройти через них и получить 10)

Теоретически этот код делает именно то, что я хочу, поскольку он "получает" 10 самых последних обзоров для каждого местоположения. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу просто res.send() из-за того, что она отправляет перед завершением каждого запроса. Я попытался добавить к returnObj и затем отправить его, как указано выше, но, похоже, это не работает.

Может ли кто-нибудь помочь мне выяснить, как получить данные в одном запросе или как я могу заставить это ждать, пока не будут запрошены все местоположения, для которых были получены последние обзоры?

1 Ответ

1 голос
/ 07 ноября 2019

Операция базы данных асинхронна в nodejs, поэтому вам нужно обрабатывать асинхронное поведение, и вы не можете вызывать запрос mysql внутри цикла for. так вот ваше окончательное решение

    import { resolve } from "path";
import { rejects } from "assert";

var returnObj = [];

router.get('/', (req, res) => {
    const LocationsQuery = 'SELECT locationID FROM locations GROUP BY locationID';

    connection.getConnection(function (err, connection) {
        connection.beginTransaction(function (err) {
            if (err) {
                connection.rollback(function () {
                    connection.release();
                });
            } else {
                connection.query(LocationsQuery, function (err, results) {
                    if (err) {
                        connection.rollback(function () {
                            connection.release();
                        });
                    }
                    var promises = [];
                    for (var i = 0; i < results.length; i++) {
                        promises.push(performopration, results[i], config);
                    } //End For loop

                    Promise.all(promises)
                    .then(() => {
                        res.send(returnObj);
                    })
                });
            }
        });
    });
});

function performopration(connection, results, config) {
    var dataQuery = `SELECT  locations.businessName, locations.address, locations.city, locations.state, locations.zipCode, locations.Country, r.comfort,
                                            r.timeliness, r.politeness, r.accessibility, r.averageRating, r.food, r.breakRoom, r.restroom
                                            FROM (SELECT reviews.locationID, reviews.comfort,  reviews.timeliness, reviews.politeness,  reviews.accessibility,
                                                    (reviews.comfort +  reviews.timeliness + reviews.politeness +  reviews.accessibility) / 4 AS averageRating, 
                                                    reviews.food, reviews.breakRoom, reviews.restroom
                                                    FROM reviews 
                                                    WHERE reviews.locationID = ${results.locationID}) r 
                                        LEFT JOIN locations on locations.locationID = r.locationID   
                                        LIMIT ${config.limit}`;

    return new Promise((resolve, rejects) => {
        connection.query(dataQuery, function (err, res) {

            if (err) {
                connection.rollback(function () {
                    connection.release();
                });
                rejects();
            }

            //Get the Averages of the ratings then creates 
            // Json Object out of the MYSQL return Data 
            object = setup(res)
            returnObj.append(object);
            console.log(object);
            resolve();
        })
    })


}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...