将Mongodb ObjectId自动映射到字符串或从字符串映射

时间:2012-07-13 17:52:19

标签: mongodb clojure monger

我使用Monger库从Clojure访问Mongo数据库。令我烦恼的一件事是在ObjectId实例和字符串之间来回切换。

例如,此代码(mc/find-maps "posts" {})将评估映射,其中_id条目的值设置为ObjectId类的实例,而在我的应用中,我发现它更简单把它作为一个字符串,我知道它是独一无二的。

另一方面,对于(mc/find-map-by-id "posts" (new ObjectId id))之类的表达式,我在id参数中使用String对象,我必须使用它来构造ObjectId的实例。

有没有办法让_id的值自动透明地在应用程序中的字符串和mongo端的ObjectId之间进行转换?某种选项在启用时会创建带有ids字符串表示的地图,反之亦然会在用作查询中的参数时转换ids t对象ID的字符串表示形式?

如果没有,还有哪些其他策略?

2 个答案:

答案 0 :(得分:1)

我在这一点上与你分享痛苦。回到ObjectID是很烦人的,因为你总是要来回转换,如果你忘了,那就很难捕捉到它。

您最好的选择可能是包装驱动程序代码以自动执行转换。因此,使用查看类型的瘦包装替换find,findOne,insert,无论您是进入还是退出,都会自动进行转换。

不幸的是,我认为没有更简单的方法。

答案 1 :(得分:0)

我参加聚会有点晚了,但必须为子孙后代提及。

由于要让代码了解必须将哪些字符串视为ObjectID以及哪些不能视为ObjectID的代码很复杂,因此我不打算解决自动的str-> ObjectID部分。但是对于ObjectID-> str一半,有一个解决方案。

我最终像这样扩展了monger.conversion/ConvertFromDBObject协议:

(extend-protocol ConvertFromDBObject
    ObjectId
    (from-db-object [input keywordize]
      (str input)))

from-db-object在所有读取为地图操作上被调用,因此解决了读取部分。至于将ObjectID转换为字符串以进行插入和更新的结果,我还没有找到任何优雅的解决方案,并为该映射扩展了相同的协议,并在包装​​函数中对插入和更新操作的结果调用了from-db-object。扩展地图协议看起来像这样(从DBObject的原始实现中完全被盗:

(extend-protocol ConvertFromDBObject
    ; copied over from the implementation for DBObject
    clojure.lang.IPersistentMap
    (from-db-object [input keywordize]
      (reduce (if keywordize
                (fn [m ^String k]
                  (assoc m (keyword k) (from-db-object (.get input k) true)))
                (fn [m ^String k]
                  (assoc m k (from-db-object (.get input k) false))))
              {} (.keySet input))))