如何使用Node.js在IBM数据库中进行MongoDB的地理空间查询?

huangapple go评论70阅读模式
英文:

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 - URL
  • MONGO_CERT_FILE - CA证书的路径

您可以从IBM Cloud仪表板获取服务的URL和证书。

脚本在名为 "locations" 的目录中查找GeoJSON文件,并将它们插入由环境变量指定的数据库/集合中。

它还指示MongoDB在数据的 "geometry" 属性上创建一个地理空间索引:

await collection.createIndex( { geometry: "2dsphere" } )

这表示"在存储在 'geometry' 属性中的数据上创建一个 '2dsphere' 索引"。

现在我们已准备好查询集合。

我们需要候选的天气事件,以GeoJSON格式表示,例如:

如何使用Node.js在IBM数据库中进行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 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(&#39;Missing MONGO configuration&#39;)
  process.exit(1)
}

// constants
const DATA_DIR = &#39;./locations&#39;

// import dependencies
const fs = require(&#39;fs&#39;)
const path = require(&#39;path&#39;)
const mongodb = require(&#39;mongodb&#39;)

const main = async () =&gt; {
  // 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: &#39;utf8&#39; })
    const obj = JSON.parse(contents)
    await collection.insertOne(obj)
    console.log(&#39;Inserted&#39;, obj._id)
  }

  // create geospatial index
  await collection.createIndex( { geometry: &quot;2dsphere&quot; } )
  console.log(&#39;created geospatial index&#39;)
  
  // exit
  process.exit()
}

main()

This script expects your MongoDB service's credentials to be in environment variables:

  • MONGO_DB - the database name
  • MONGO_COLLECTION - collection name
  • MONGO_URI - the URL
  • MONGO_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: &quot;2dsphere&quot; } )

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.

如何使用Node.js在IBM数据库中进行MongoDB的地理空间查询?

> 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(&#39;Missing MONGO configuration&#39;)
  process.exit(1)
}

// import dependencies
const fs = require(&#39;fs&#39;)
const mongodb = require(&#39;mongodb&#39;)

const main = async () =&gt; {
  // 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(&#39;./storm.geojson&#39;, { encoding: &#39;utf8&#39; })
  const storm = JSON.parse(data)

  // find which locations are affected by the storm
  const results = await collection.find({
    geometry: {
      &#39;$geoIntersects&#39; : {
        &#39;$geometry&#39;: {
          type: storm.geometry.type,
          coordinates: storm.geometry.coordinates
        }
      }
    }
  }).toArray()
  
  // output the list of location ids
  console.log(results.map((r) =&gt; { return r._id }))

  // die
  process.exit()

}

main()

It loads the candidate weather event from storm.json:

{&quot;type&quot;:&quot;Feature&quot;,&quot;properties&quot;:{},&quot;geometry&quot;:{&quot;coordinates&quot;:[[[-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]]],&quot;type&quot;:&quot;Polygon&quot;}}

then performs a geospatial query using MongoDB:

  const results = await collection.find({
    geometry: {
      &#39;$geoIntersects&#39; : {
        &#39;$geometry&#39;: {
          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:

[ &#39;south carolina&#39;, &#39;north carolina&#39;, &#39;georgia&#39;, &#39;florida&#39; ]

huangapple
  • 本文由 发表于 2023年5月10日 18:33:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76217362.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定