具有sequelize和节点js的Mysql本机空间函数
我在我的mysql数据库中存储一个POINTtypes的位置:
module.exports = function (sequelize, DataTypes) { var Promotion = sequelize.define('promotion', { userId: { type: DataTypes.STRING, allowNull: false }, location: { type: DataTypes.GEOMETRY('POINT'), allowNull: false }
它看起来像点被正确存储:
我试图使用mysql本机ST_MakeEnvelope
函数查找一组边界内的所有行。 我用这个postgresql和它完美的工作,但是当我切换到MySQL它开始抛出错误:
if (northEastLng && northEastLat && southWestLat && southWestLng) { where.location = { $overlap: db.sequelize.fn('ST_MakeEnvelope', southWestLng, southWestLat, northEastLng, northEastLat) } } promotion.findAll({ where, }) .then(promoters => { res.json(promoters) }) .catch(err => { console.log('ERROR: ', err) })
错误:
Error: ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT: Incorrect parameter count in the call to native function 'ST_MakeEnvelope'
所以我尝试了两点:
const POINT_ONE = `POINT(${southWestLng} ${southWestLat})` const POINT_TWO = `POINT(${northEastLng} ${northEastLat})` where.location = { $overlap: db.sequelize.fn('ST_MakeEnvelope', POINT_ONE, POINT_TWO) }
现在我得到这个错误:
SequelizeDatabaseError: UNKNOWN_CODE_PLEASE_REPORT: Geometry byte string must be little endian.
一直在四处寻找,而不太确定从哪里去。 如何使用ST_MakeEnvelope
函数和sequelize进行查询?
编辑
从piotrbienias响应中添加生成的sql:
SELECT `promotion`.`id`, `promotion`.`userId`, `promotion`.`title`, `promotion`.`description`, `promotion`.`startDate`, `promotion`.`endDate`, `promotion`.`isIndefinite`, `promotion`.`isApproved`, `promotion`.`status`, `promotion`.`reach`, `promotion`.`trustRanking`, `promotion`.`isLocationBased`, `promotion`.`address`, `promotion`.`city`, `promotion`.`state`, `promotion`.`zip`, `promotion`.`location`, `promotion`.`createdAt`, `promotion`.`updatedAt`, `promotion`.`categoryId `, `promotionImages`.`id` AS `promotionImages.id`, `promotionImages`.`url` AS `promotionImages.url`, `promotionImages`.`publicId` AS `promotionImages.publicId`, `promotionImages`.`secureUrl` AS `promotionImages.secureUrl`, `promotionImages`.`isApproved` AS `promotionImages.isApproved`, `promotionImages`.`createdAt` AS `promotionImages.createdAt`, `promotionImages`.`updatedAt` AS `promotionImages.updatedAt`, `promotionImages`.`promotionId` AS `promotionImages.promotionId`, `category`.`id` AS `cat egory.id`, `category`.`title` AS `category.title` FROM `promotions` AS `promotion` LEFT OUTER JOIN `promotionImages` AS `promotionImages` ON `promotion`.`id` = `promotionImages`.`promotionId` LEFT OUTER JOIN `categories` AS `category` ON `promotion`.`categoryId` = `category`.`id` WHERE `promotion`.`location` && ST_MakeEnvelope(ST_GeomFromText('POINT(-80.30252222253421 25.802030960352745)'), ST_GeomFromText('POINT(-80.30252222253421 25.802030960352745)'));
我不熟悉MySQL的Geometry部分,但不应该在使用它们之前在这些点上使用ST_GeomFromText
函数?
where.location = { $overlap: db.sequelize.fn( 'ST_MakeEnvelope', db.sequelize.fn('ST_GeomFromText', POINT_ONE), db.sequelize.fn('ST_GeomFromText', POINT_TWO), ) } };
就像它在ST_MakeEnvelope
函数的例子中所表示的ST_MakeEnvelope
(并且它需要两个参数,所以这可能是您的第一个错误的原因Incorrect parameter count in the call to native function 'ST_MakeEnvelope'
)。 而且,正如我一开始所说的,我绝对不是这方面的专家,只是看了一下MySQL文档后的build议。
编辑
以下是来自Sequelize文档的$overlap
描述
$ overlap:[1,2] // && [1,2](PG数组重叠操作符)
我认为你应该build立你的Sequelize查询不同,没有$overlap
。 我想你应该使用ST_Contains
函数,你的where
对象应该如下
{ where: db.sequelize.where( db.sequelize.fn( 'ST_Contains', db.sequelize.fn( 'ST_MakeEnvelope', db.sequelize.fn('ST_GeomFromText', POINT_ONE), db.sequelize.fn('ST_GeomFromText', POINT_TWO) ), db.sequelize.col('promotion.location') ), '=', 1 ) }
在我看来,你想要的SQL应该是这样的:
WHERE ST_Contains(POLYGON(...), location)
上面的Sequelize查询会生成
WHERE ST_Contains(ST_MakeEnvelope(ST_GeomFromText(POINT_ONE), ST_GeomFromText(POINT_TWO)), location) = 1;
应该检查从两点创build的多边形是否包含location
列的值。 ST_Contains
返回1或0,所以我认为在这种情况下= 1
条件应该是可以的。