【问题标题】:MongoDB : how to index the keys of a MapMongoDB:如何索引 Map 的键
【发布时间】:2012-06-17 20:55:08
【问题描述】:

在 Java 中,我有一个看起来像这样的对象:

class MyDoc {
     ObjectId docId;
     Map<String, String> someProps = new HashMap<String,String>(); 
}

当持久化到 MongoDB 时会生成以下文档:

{
    "_id" : ObjectId("4fb538eb5e9e7b17b211d5d3"),
    "someProps" : {
        "4fda4993eb14ea4a4a149c04" : "PROCESSED",
        "4f56a5c4b6f621f092b00525" : "PROCESSED",
        "4fd95a2a0baaefd1837fe504" : "TODO"
    }
}

我需要查询如下。

DBObject queryObj =  
new BasicDBObject("someProps.4fda4993eb14ea4a4a149c04","PROCESSED");                        
DBObject explain =  
getCollection().find(queryObj).hint("props_indx").explain();

这应该是找到我的 MyDoc 文档,这些文档有一个 someProps,键为“4fda4993eb14ea4a4a149c04”,值为“Processed”

我在集合中存储了数百万个 MyDoc 文档,因此我需要对 someProps 嵌入对象的键进行有效索引。

事先不知道地图的键(它们是动态生成的,它们不是一组固定的键),因此我无法为每个 someProps 键创建一个索引。 (至少我不认为如果我错了我可以纠正我)

我尝试直接在 someProps 上创建索引,但查询需要很长时间。

如何索引 someProps Map 键? 我需要不同的文档结构吗?

重要提示:

1 . someProps 中只能有一个元素具有相同的键。例如:

{
"_id" : ObjectId("4fb538eb5e9e7b17b211d5d3"),
    "someProps" : {
        "4fda4993eb14ea4a4a149c04" : "PROCESSED",
        "4f56a5c4b6f621f092b00525" : "PROCESSED",
        "4f56a5c4b6f621f092b00525" : "TODO"
    }
}

将无效,因为 4f56a5c4b6f621f092b00525 在地图中找不到两次(因此首先使用地图)

2 。我还需要有效地更新 someProps,只更改值(例如:将“4fda4993eb14ea4a4a149c04”:“PROCESSED”更改为“4fda4993eb14ea4a4a149c04”:“CANCELLED”)

我有什么选择?

谢谢。

【问题讨论】:

  • 看起来最好将这些设置移动到单独的文档中。
  • @Sergio : 你的意思是把文档 somProps 放在一个单独的集合中吗?
  • 是的,我会将来自someProps 的每个条目制作成一个单独的文档。
  • 将它们放在另一个集合中会解决索引未知键名的问题吗?恐怕我没看到。
  • 是的,它会变成这样:{k: '4fda4993eb14ea4a4a149c04', v: 'PROCESSED'}。这是完全可索引的。

标签: java mongodb


【解决方案1】:

如果你想保持你的属性嵌入,你也可以使用 Kyle Banke 在“MongoDB in Action”中提出的动态属性模式。因此,您无需将道具放在自己的集合中,而是将 mydocs 集合修改为如下所示:

{
  "_id" : ObjectId("4fb538eb5e9e7b17b211d5d3"),
  "someProps" : [
      { k: "4fda4993eb14ea4a4a149c04", v: "PROCESSED" },
      { k: "4f56a5c4b6f621f092b00525", v: "PROCESSED" },
      { k: "4fd95a2a0baaefd1837fe504", v : "TODO" }
  ]
}

然后对嵌入的文档键进行索引:

db.mydoc.ensureIndex({'someProps.k' :1}, {'someProps.v' :1})

这与 Sergio 的建议非常接近,但您的数据仍将是单个集合中的一个文档。

【讨论】:

  • 不应该是db.mydoc.ensureIndex({'someProps' :1})像例子那样高效搜索特定的键值对吗?
  • 或者经过更多思考db.mydoc.ensureIndex({'someProps.k' :1, 'someProps.v':1}),基于docs.mongodb.com/manual/core/index-multikey/…
【解决方案2】:

如何像这样构建您的文档:

{
"_id" : ObjectId("4fb538eb5e9e7b17b211d5d3"),
    "someProps" : {
        "PROCESSED":["4fda4993eb14ea4a4a149c04","4f56a5c4b6f621f092b00525"],
        "TODO" : ["4f56a5c4b6f621f092b00526"],
        "CANCELLED" : [ ]
    }
}

这样做的三个优点是:

  1. 您可以通过从 “someProps.4fda4993eb14ea4a4a149c04”,“已处理”到 "someProps.PROCESSED", "4fda4993eb14ea4a4a149c04"

  2. 您可以在“someProps.TODO”上创建一个索引,在“someProps.PROCESSED”上创建另一个索引(您不能在多个并行数组上创建复合索引,但听起来您会通过一个单身状态,对吧?

  3. 您可以自动将文档从一种状态移动到另一种状态,如下所示:

.

db.collection.update({"someProps.PROCESSED": "4fda4993eb14ea4a4a149c04"},
                     {$pull:{"someProps.PROCESSED":"4fda4993eb14ea4a4a149c04"},
                      $push:{"someProps.CANCELLED":"4fda4993eb14ea4a4a149c04"}});

【讨论】:

  • 谢谢!我本可以发誓我在运行它后从我的 shell 中剪切并粘贴它,但我想我在试图格式化它时打破了它——也感谢你修复它:)
  • 这是一个伟大的贡献。另一个小考虑:您必须确保 ID 在应用程序级别不会出现多次(在多个类别中)。当你 $pull 一个不存在的值时,你会得到一个错误吗?
【解决方案3】:

我建议将这些属性扩展到它们自己的文档中。所以你的例子:

{
    "_id" : ObjectId("4fb538eb5e9e7b17b211d5d3"),
    "someProps" : {
        "4fda4993eb14ea4a4a149c04" : "PROCESSED",
        "4f56a5c4b6f621f092b00525" : "PROCESSED",
        "4fd95a2a0baaefd1837fe504" : "TODO"
    }
}

变成这样

{_id: {id1: ObjectId("4fb538eb5e9e7b17b211d5d3"), id2: "4fda4993eb14ea4a4a149c04"}, v: "PROCESSED"}
{_id: {id1: ObjectId("4fb538eb5e9e7b17b211d5d3"), id2: "4f56a5c4b6f621f092b00525"}, v: "PROCESSED"}
{_id: {id1: ObjectId("4fb538eb5e9e7b17b211d5d3"), id2: "4fd95a2a0baaefd1837fe504"}, v: "TODO"}

这里id1 是您以前的父实体的ID(无论是应用程序还是其他),id2 是属性ID。

唯一性由_id 字段的属性强制执行。原子更新是微不足道的。索引很容易

db.props.ensureIndex({'_id.id2': 1})

唯一的缺点是一些存储开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 2012-08-22
    • 2011-11-15
    • 1970-01-01
    • 2013-06-17
    • 2018-10-27
    • 1970-01-01
    相关资源
    最近更新 更多