草庐IT

mongodb - 如果尚未给出对象属性,则将对象添加到对象数组

coder 2023-11-04 原文

用例

我有一个集合 band_profiles 和一个集合 band_profiles_history。历史集合应该每 24 小时存储一次 band_profile 快照,因此我使用 MongoDB 推荐的历史跟踪格式:每个月+年都是它自己的文档,在一个对象数组中我将存储 bandProfile 快照以及当前日期这个月。

我的模型:

band_profiles_history 中的文档如下所示:

{
    "_id" : ObjectId("599e3bc406955db4cbffe0a8"),
    "month" : 7,
    "tag_lowercased" : "9yq88gg",
    "year" : 2017,
    "values" : [
        {
            "_id" : ObjectId("599e3bc41c073a7418fead91"),
            "profile" : {
                "_id" : ObjectId("5989a65d0f39d9fd70cde1fe"),
                "tag" : "9YQ88GG",
                "name_normalized" : "example name1",
            },
            "day" : 1
        },
        {
            "_id" : ObjectId("599e3bc41c073a7418fead91"),
            "profile" : {
                "_id" : ObjectId("5989a65d0f39d9fd70cde1fe"),
                "tag" : "9YQ88GG",
                "name_normalized" : "new name",
            },
            "day" : 2
        }
    ]
}

band_profiles 中的文档:

{
    "_id" : ObjectId("5989a6190f39d9fd70cddeb1"),
    "tag" : "9V9LRGU",
    "name_normalized" : "example name",
    "tag_lowercased" : "9v9lrgu",
}

这就是我目前将文档更新到 band_profiles_history 的方式:

BandProfileHistory.update(
  { tag_lowercased: tag, year, month},
  { $push: {
        values: { day, profile }
    }
  }, 
  { upsert: true }
)

我的问题:

我只想每天插入一个快照。现在它总是将一个新对象插入对象数组values,不管我那天是否已经有一个对象。如果当天还没有对象,我如何实现它只会推送该对象?

最佳答案

暂且把 mongoose 放在一边:

有一个操作addToSet它将向数组添加一个元素(如果它尚不存在)。

警告:

If the value is a document, MongoDB determines that the document is a duplicate if an existing document in the array matches the to-be-added document exactly; i.e. the existing document has the exact same fields and values and the fields are in the same order. As such, field order matters and you cannot specify that MongoDB compare only a subset of the fields in the document to determine whether the document is a duplicate of an existing array element.

由于您尝试添加整个文档,因此您受到此限制。

所以我看到了以下解决方案:

解决方案一:

读入数组,看看它是否包含你想要的元素,如果没有则将它推送到values。数组 push .

缺点 NOT 是一个原子操作,这意味着您最终可能会重复。如果您运行定期清理作业以从每个文档的该字段中删除重复项,这可能是可以接受的。

这是否可以接受由您决定。

方案二:

假设您将字段 _id在你的子文档中 values领域,停止这样做。假设 Mongoose 正在为你做这件事(因为它确实如此,据我所知)阻止它像这里所说的那样做:Stop mongoose from creating _id for subdocument in arrays .

接下来您需要确保文档中的字段始终具有相同的顺序,因为在比较 addToSet 中的文档时顺序很重要上述引用中所述的操作。

方案三

更改 band_profiles_history 的架构类似于:

{
    "_id" : ObjectId("599e3bc406955db4cbffe0a8"),
    "month" : 7,
    "tag_lowercased" : "9yq88gg",
    "year" : 2017,
    "values" : {
       "1": { "_id" : ObjectId("599e3bc41c073a7418fead91"),
            "profile" : {
                "_id" : ObjectId("5989a65d0f39d9fd70cde1fe"),
                "tag" : "9YQ88GG",
                "name_normalized" : "example name1"
            }
        },
        "2": {
            "_id" : ObjectId("599e3bc41c073a7418fead91"),
            "profile" : {
                "_id" : ObjectId("5989a65d0f39d9fd70cde1fe"),
                "tag" : "9YQ88GG",
                "name_normalized" : "new name"
            }
        }

}

请注意,day 字段成为 values 上子文档的键。 .还要注意 values现在是 Object而不是 Array .

不,您可以运行更新查询来更新 values.<day>仅当values.<day>不存在。

我个人不喜欢这个,因为它使用了 JSON 不允许重复键来支持模式这一事实。

关于mongodb - 如果尚未给出对象属性,则将对象添加到对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45964109/

有关mongodb - 如果尚未给出对象属性,则将对象添加到对象数组的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  5. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  6. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  9. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  10. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

随机推荐