英文:
How do I do geospatial queries using IBM Databases for MongoDB using Node.js?
问题
你可以使用MongoDB来执行此查询,以查找与给定的GeoJSON风暴对象相交的美国州份。
英文:
I have collection GeoJSON locations that represent US states. How can I find which states intersect a hypothetical storm which is also a GeoJSON object? Can MongoDB perform this query?
答案1
得分: 3
以下是翻译好的代码部分:
首先,我们需要一个包含美国各州的MongoDB集合,以GeoJSON格式存储,例如 https://github.com/glynnbird/usstatesgeojson。我们可以使用一个Node.js脚本将数据导入到新的MongoDB数据库/集合中:
// 连接凭据
const MONGO_DB = process.env.MONGO_DB
const MONGO_COLLECTION = process.env.MONGO_COLLECTION
const MONGO_URI = process.env.MONGO_URI
const MONGO_CERT_FILE = process.env.MONGO_CERT_FILE
if (!MONGO_DB || !MONGO_COLLECTION || !MONGO_URI || !MONGO_CERT_FILE) {
console.error('缺少MONGO配置')
process.exit(1)
}
// 常量
const DATA_DIR = './locations';
// 导入依赖项
const fs = require('fs')
const path = require('path')
const mongodb = require('mongodb')
const main = async () => {
// 连接到MongoDB
const MongoClient = mongodb.MongoClient
const opts = {
tls: true,
tlsCAFile: MONGO_CERT_FILE,
useUnifiedTopology: true,
useNewUrlParser: true
}
const mongoClient = new MongoClient(MONGO_URI, opts)
await mongoClient.connect()
// 创建数据库和集合
const db = await mongoClient.db(MONGO_DB)
const collection = db.collection(MONGO_COLLECTION)
// 获取要导入的数据文件列表
const files = fs.readdirSync(DATA_DIR)
for(const f of files) {
const contents = fs.readFileSync(path.join(DATA_DIR, f), { encoding: 'utf8' })
const obj = JSON.parse(contents)
await collection.insertOne(obj)
console.log('已插入', obj._id)
}
// 创建地理空间索引
await collection.createIndex( { geometry: "2dsphere" } )
console.log('已创建地理空间索引')
// 退出
process.exit()
}
main()
这个脚本期望您的MongoDB服务的凭据存储在环境变量中:
MONGO_DB
- 数据库名称MONGO_COLLECTION
- 集合名称MONGO_URI
- URLMONGO_CERT_FILE
- CA证书的路径
您可以从IBM Cloud仪表板获取服务的URL和证书。
脚本在名为 "locations" 的目录中查找GeoJSON文件,并将它们插入由环境变量指定的数据库/集合中。
它还指示MongoDB在数据的 "geometry" 属性上创建一个地理空间索引:
await collection.createIndex( { geometry: "2dsphere" } )
这表示"在存储在 'geometry' 属性中的数据上创建一个 '2dsphere' 索引"。
现在我们已准备好查询集合。
我们需要候选的天气事件,以GeoJSON格式表示,例如:
请注意,这场风暴涵盖了四个美国州。
查询代码如下,使用与第一个脚本相同的环境变量:
// 连接凭据
const MONGO_DB = process.env.MONGO_DB
const MONGO_COLLECTION = process.env.MONGO_COLLECTION
const MONGO_URI = process.env.MONGO_URI
const MONGO_CERT_FILE = process.env.MONGO_CERT_FILE
if (!MONGO_DB || !MONGO_COLLECTION || !MONGO_URI || !MONGO_CERT_FILE) {
console.error('缺少MONGO配置')
process.exit(1)
}
// 导入依赖项
const fs = require('fs')
const mongodb = require('mongodb')
const main = async () => {
// 连接到MongoDB
const MongoClient = mongodb.MongoClient
const opts = {
tls: true,
tlsCAFile: MONGO_CERT_FILE,
useUnifiedTopology: true,
useNewUrlParser: true
}
const mongoClient = new MongoClient(MONGO_URI, opts)
await mongoClient.connect()
// 配置数据库和集合
const db = await mongoClient.db(MONGO_DB)
const collection = db.collection(MONGO_COLLECTION)
// 这是我们的输入天气事件
const data = fs.readFileSync('./storm.geojson', { encoding: 'utf8' })
const storm = JSON.parse(data)
// 查找受风暴影响的位置
const results = await collection.find({
geometry: {
'$geoIntersects' : {
'$geometry': {
type: storm.geometry.type,
coordinates: storm.geometry.coordinates
}
}
}
}).toArray()
// 输出位置id列表
console.log(results.map((r) => { return r._id }))
// 退出
process.exit()
}
main()
它从 storm.json
中加载候选的天气事件:
{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-77.00416876685775,34.60867695038871],[-78.93776251685789,35.1134983061437],[-80.99220587623299,35.158420777504745],[-83.65089728248286,34.671948926428996],[-83.85963751685802,33.891272054223364],[-83.84865118873311,32.010746736868654],[-83.31032111060784,31.309406168163207],[-82.45338751685738,30.6311690732732],[-80.15724493873236,30.385070283872437],[-79.03663946998299,30.49873173190622],[-77.44362189185789,31.674764007288985],[-76.56471564185757,33.029728245050364],[-76.64161993873286,33.69040245253204],[-77.00416876685775,34.60867695038871]]],"type":"Polygon"}}
然后使用MongoDB执行地理空间查询:
const results = await collection.find({
geometry: {
'$geoIntersects' : {
'$geometry': {
type: storm.geometry.type,
coordinates: storm.geometry.coordinates
}
}
}
}).toArray()
这转化为"查找其 'geometry' 字段与风暴的几何图形相交的文档"。
脚本输出四个结果:
[ '南卡罗来纳',
<details>
<summary>英文:</summary>
First we need a MongoDB collection that contains the US states as GeoJSON e..g https://github.com/glynnbird/usstatesgeojson. We can import the data into a new MongoDB database/collection using a Node.js script:
```js
// connection credentials
const MONGO_DB = process.env.MONGO_DB
const MONGO_COLLECTION = process.env.MONGO_COLLECTION
const MONGO_URI = process.env.MONGO_URI
const MONGO_CERT_FILE = process.env.MONGO_CERT_FILE
if (!MONGO_DB || !MONGO_COLLECTION || !MONGO_URI || !MONGO_CERT_FILE) {
console.error('Missing MONGO configuration')
process.exit(1)
}
// constants
const DATA_DIR = './locations'
// import dependencies
const fs = require('fs')
const path = require('path')
const mongodb = require('mongodb')
const main = async () => {
// connect to MongoDB
const MongoClient = mongodb.MongoClient
const opts = {
tls: true,
tlsCAFile: MONGO_CERT_FILE,
useUnifiedTopology: true,
useNewUrlParser: true
}
const mongoClient = new MongoClient(MONGO_URI, opts)
await mongoClient.connect()
// create db and collection
const db = await mongoClient.db(MONGO_DB)
const collection = db.collection(MONGO_COLLECTION)
// get a list of data files to import
const files = fs.readdirSync(DATA_DIR)
for(const f of files) {
const contents = fs.readFileSync(path.join(DATA_DIR, f), { encoding: 'utf8' })
const obj = JSON.parse(contents)
await collection.insertOne(obj)
console.log('Inserted', obj._id)
}
// create geospatial index
await collection.createIndex( { geometry: "2dsphere" } )
console.log('created geospatial index')
// exit
process.exit()
}
main()
This script expects your MongoDB service's credentials to be in environment variables:
MONGO_DB
- the database nameMONGO_COLLECTION
- collection nameMONGO_URI
- the URLMONGO_CERT_FILE
- the path of the CA certificate
> You can obtain your service's URL and certificate from the IBM Cloud dashboard.
The script looks for the GeoJSON files in a directory called "locations" and inserts them into a database/collection specified by the environment variables.
It also instructs MongoDB to create a geospatial index on the data's "geometry" attribute:
await collection.createIndex( { geometry: "2dsphere" } )
This says "create a '2dsphere' index on the data stored in the 'geometry' attribute".
We are now ready to query the collection.
We need candidate weather event, expressed as GeoJSON e.g.
> Notice that the storm overlaps four US states.
The query code is as follows and uses the same environment variables as the first script:
// connection credentials
const MONGO_DB = process.env.MONGO_DB
const MONGO_COLLECTION = process.env.MONGO_COLLECTION
const MONGO_URI = process.env.MONGO_URI
const MONGO_CERT_FILE = process.env.MONGO_CERT_FILE
if (!MONGO_DB || !MONGO_COLLECTION || !MONGO_URI || !MONGO_CERT_FILE) {
console.error('Missing MONGO configuration')
process.exit(1)
}
// import dependencies
const fs = require('fs')
const mongodb = require('mongodb')
const main = async () => {
// connect to MongoDB
const MongoClient = mongodb.MongoClient
const opts = {
tls: true,
tlsCAFile: MONGO_CERT_FILE,
useUnifiedTopology: true,
useNewUrlParser: true
}
const mongoClient = new MongoClient(MONGO_URI, opts)
await mongoClient.connect()
// configure db and collection
const db = await mongoClient.db(MONGO_DB)
const collection = db.collection(MONGO_COLLECTION)
// this is our incoming weather event
const data = fs.readFileSync('./storm.geojson', { encoding: 'utf8' })
const storm = JSON.parse(data)
// find which locations are affected by the storm
const results = await collection.find({
geometry: {
'$geoIntersects' : {
'$geometry': {
type: storm.geometry.type,
coordinates: storm.geometry.coordinates
}
}
}
}).toArray()
// output the list of location ids
console.log(results.map((r) => { return r._id }))
// die
process.exit()
}
main()
It loads the candidate weather event from storm.json
:
{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-77.00416876685775,34.60867695038871],[-78.93776251685789,35.1134983061437],[-80.99220587623299,35.158420777504745],[-83.65089728248286,34.671948926428996],[-83.85963751685802,33.891272054223364],[-83.84865118873311,32.010746736868654],[-83.31032111060784,31.309406168163207],[-82.45338751685738,30.6311690732732],[-80.15724493873236,30.385070283872437],[-79.03663946998299,30.49873173190622],[-77.44362189185789,31.674764007288985],[-76.56471564185757,33.029728245050364],[-76.64161993873286,33.69040245253204],[-77.00416876685775,34.60867695038871]]],"type":"Polygon"}}
then performs a geospatial query using MongoDB:
const results = await collection.find({
geometry: {
'$geoIntersects' : {
'$geometry': {
type: storm.geometry.type,
coordinates: storm.geometry.coordinates
}
}
}
}).toArray()
This translates to "find documents whose 'geometry' field intersects the geometry of the storm".
The script outputs four results:
[ 'south carolina', 'north carolina', 'georgia', 'florida' ]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论