【问题标题】:How to re-structure a MongoDb collection如何重新构建 MongoDb 集合
【发布时间】:2014-07-28 15:40:52
【问题描述】:

我需要用这种结构查询一个 MongoDb 集合:

{
"_id" : ObjectId("53cfc8bf8f11381e28373153"),
"name" : "0700452",
"description" : "",
"styleurl" : "#style00001",
 "point" : {
    "altitudemode" : "clampToGround",
    "coordinates" : "11.8263919657018, 41.2129293739724, 1.02757364822173"
 }
}

我需要做的查询类型是基于 2dsphere 索引搜索,但是当我尝试这个时:

db.coordinatas.find({ $near : { type:'Point', point:{coordinates:"15.8263919657018, 41.2129293739724"}, $maxDistance : 100 }});

我得到一个错误:

error: {
    "$err" : "can't find any special indices: 2d (needs index), 2dsphere (needs index),  for: { $near: { type: \"Point\", point: { coordinates: \"15.8263919657018, 41.2129293739724\" }, $maxDistance: 100.0 } }",
    "code" : 13038
}

与错误所说的索引相反:

[
{
    "v" : 1,
    "key" : {
        "_id" : 1
    },
    "ns" : "test4-dev.coordinatas",
    "name" : "_id_"
},
{
    "v" : 1,
    "key" : {
        "coordinates" : "2dsphere"
    },
    "ns" : "test4-dev.coordinatas",
    "name" : "coordinates"
}

]

这可能是因为 2dsphere 索引需要一个包含两个坐标的数组。
我在想也许我可以用这种新格式重组集合:

{
"_id" : ObjectId("53cfc8bf8f11381e28373153"),
"name" : "0700452",
"coordinates": [11.8263919657018, 41.2129293739724]
}

并以这种方式查询集合:

db.coordinatas.find({ $near : {type:'Point', coordinates:[11.8263919657018, 41.2129293739724], $maxDistance : 100 }});

如何在新集合中更改旧集合的格式?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    this page 中所述:

    [2dsphere] 索引支持存储为 GeoJSON 对象和旧坐标对的数据。该索引通过将数据转换为 GeoJSON Point 类型来支持旧坐标对。

    如果您要转换数据,我建议您将其转换为 GeoJSON point,如下所示:

    { loc: { type: "Point", coordinates: [ 11.8263919657018, 41.2129293739724 ] } } 
    

    为此,您必须运行一个脚本,在其中执行以下操作:

    1. 遍历所有文档。
    2. 为每个文档检索两个坐标值。
    3. 使用新的坐标值,创建一个 GeoJSON 字段。
    4. 取消设置上一个字段。

    转换完所有文档后,您可以删除旧索引并使用新字段名称构建新索引。

    更新:

    作为参考,这是一种通过mongo shell 更新集合的方法。您可能会发现它很有用。

    // Iterate through all the documents and set the new field
    // with the GeoJSON point using the old coordinates string. 
    db.coords.find().forEach(function(doc) {
        var id = doc._id,
            coords = doc.point.coordinates.split(", ");
    
        db.coords.update({ "_id" : id }, { $set : { "point.loc.type": "Point", "point.loc.coordinates": [ coords[0], coords[1] ] } });
    });
    
    // Unset the old field from all the documents
    db.coords.update({}, { $unset: { "point.coordinates" : 1 } }, { "multi": true });
    

    【讨论】:

    • @Cris69,太棒了。我为mongo shell 添加了一些示例代码,以防万一。
    【解决方案2】:

    MongoDB 的字符串操作还不够先进,无法完全在数据库上执行此操作,因此您必须使用 MongoDB shell 中的一个小程序来完成。或者,您可以使用您最喜欢的具有 MongoDB 驱动程序的编程语言来执行此操作。

    1. 创建一个空的db.collection.find() 查询以获取集合中每个文档的光标
    2. 对于您找到的每个文档,将坐标字段中的字符串拆分为浮点值数组
    3. save 将文档返回到集合(保存功能将搜索具有相同 _id 的文档并更新它,当找不到时它会创建一个新文档,这在您的情况下不会发生,因为您从数据库)

    【讨论】:

      猜你喜欢
      • 2011-04-27
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      • 2017-03-11
      • 2021-12-07
      相关资源
      最近更新 更多