Используя Sequelize, как я могу получить ближайшие n элементов к широте и длине, которые находятся в радиусе этого объекта? - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть модель, которая выглядит так:

sequelize.define('region', {
    origin: {
        type: DataTypes.GEOMETRY('POINT'),
    },
    radius: {
        type: DataTypes.DOUBLE,
    }
}

Я хочу иметь возможность найти ближайший (к источнику) regions, который содержит данные latitude и longitude.

Я видел из этого вопроса, как найти ближайший n regions. Но мне нужно добавить что-то к where, которое возвращает только regions, когда расстояние между данными lat и long меньше или равно region.radius.

var query = req.query;
var latitude = query.latitude;
var longitude = query.longitude;
var limit = query.limit || 10;

const myDistance = query.maxDistance || 10000; // **** If I can get this to be `region.radius` then I think it'll work
models.Region.findAll({
    attributes: {
    include: [
        [
        models.Sequelize.fn(
            'ST_Distance',
            models.Sequelize.col('origin'),
            models.Sequelize.fn('ST_MakePoint', longitude, latitude)
        ),
        'distance'
        ]
    ]
    },
    where: models.Sequelize.where(
    models.Sequelize.fn(
        'ST_DWithin',
        models.Sequelize.col('origin'),
        models.Sequelize.fn('ST_MakePoint', longitude, latitude),
        myDistance
    ),
    true
    ), 
    order: models.Sequelize.literal('distance ASC')
}).then( regions => {
    return res.json(regions);
})

1 Ответ

0 голосов
/ 06 ноября 2018

В итоге я использовал необработанный SQL-запрос с gis:

var query = req.query;
var latitude = parseFloat(query.latitude);
var longitude = parseFloat(query.longitude);
var limit = query.limit || 10;
const maxDistance = parseFloat(query.maxDistance) || 10000;

models.sequelize.query('SELECT "id", "origin", "radius", "createdAt", "updatedAt", "regionID", ST_Distance("origin", ST_MakePoint(?, ?), false) AS "distance" FROM "regions" AS "region" WHERE ST_DWithin("origin", ST_MakePoint(?, ?), ?, false) = true AND ST_Distance("origin", ST_MakePoint(?, ?), false) - radius <= 0 ORDER BY distance ASC LIMIT ?;', { replacements: [latitude, longitude, latitude, longitude, maxDistance, latitude, longitude, limit], type: models.sequelize.QueryTypes.SELECT, model: models.Region }).then( regions => {
    return res.json(regions);
});

Вот лучше отформатированный (псевдо) оператор SQL:

SELECT *
FROM regions
WHERE ST_DWithin("origin", ST_MakePoint(lat, long), max, false) = true AND ST_Distance("origin", ST_MakePoint(lat, long), false) - radius <= 0 
ORDER BY distance ASC 
LIMIT 5;
...