7

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

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

另一方面,对于像这样的表达式:(mc/find-map-by-id "posts" (new ObjectId id))我确实使用 String 对象作为id参数,我必须使用它来构造ObjectId.

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

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

4

2 回答 2

1

我在这一点上与您分享痛苦。取回 ObjectID 很烦人,因为您总是需要来回转换,如果您忘记了,就很难发现错误。

您最好的选择可能是包装驱动程序代码以自动进行转换。因此,将 find、findOne、insert 替换为一个薄包装器,该包装器会查看类型并自动进行转换,无论您是进来还是出去。

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

于 2012-07-13T17:57:49.830 回答
0

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

我不想解决自动 str->ObjectID 部分,因为让代码了解哪些字符串必须被视为 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))))
于 2020-02-29T00:02:10.700 回答