代码之家  ›  专栏  ›  技术社区  ›  Hatshepsut

查找人们何时更改MongoDB中的属性

  •  0
  • Hatshepsut  · 技术社区  · 9 年前

    我正在尝试列出一个有人更改其 pref ,并报告他们的情况 drink 当时,忽略了他们没有改变自己 首选 .

    这个 name - location pair是一个人的唯一标识符,对于每个人来说都保持不变。

    我唯一的想法是编写一个脚本 名称 - 地方 - 首选 triple,查找与名称和位置匹配但不匹配的所有条目。我希望这是合理的。Mongo是否有一种更简单或计算上更可行的方法来做到这一点?

    {name: 'bob', location: 90210, year: 2001,  pref: 'vanilla', drink:'coffee'}
    {name: 'bob', location: 90210, year: 2002,  pref: 'vanilla', drink:'coffee'}
    {name: 'bob', location: 90210, year: 2003,  pref: 'vanilla', drink:'coffee'}
    {name: 'bob', location: 90210, year: 2004,  pref: 'chocolate', drink:'coffee'}
    {name: 'bob', location: 90210, year: 2005,  pref: 'chocolate', drink:'coffee'}
    {name: 'bob', location: 90210, year: 2006,  pref: 'chocolate', drink:'coffee'}
    {name: 'mary', location: 90210, year: 2005,  pref: 'chocolate', drink:'coffee'}
    {name: 'mary', location: 90210, year: 2006,  pref: 'chocolate', drink:'coffee'}
    

    脚本应该发现Bob改变了他的 首选 并返回他在那个领域有所改变的事实。它不应该返回关于玛丽的任何信息,因为她没有改变她 首选 。理想情况下,当鲍勃改变他的 首选 他的 去了 coffee -> 咖啡 .

    2 回复  |  直到 9 年前
        1
  •  1
  •   dikesh    9 年前

    下面是我可以使用聚合命令做的事情。

    db.test.aggregate([
        {
            $group : {
                _id : {
                    'name' : '$name',
                    'location' : '$location',
                    'pref' : '$pref'
                },
                year : {
                    '$min' : '$year'
                }
            }
        },
        {
            $sort : {
                "_id.name" : 1,
                year : 1
            }
        },
        {
            $group : {
                _id : {
                    'name' : '$_id.name',
                    'location' : '$_id.location'
                },
                from : {$first : '$_id.pref'},
                to : {$last : '$_id.pref'}
            }
        },
        {
            $project : {
                _id : 1,
                from : 1,
                to : 1,
                from_to_eq : {$eq : ['$from', '$to']}
            }
        },
        {
            $match : {
                from_to_eq : false
            }
        }
    ])
    

    它的作用是:

    聚合依据 name , location pref 并找到最低年份。 然后进行排序 名称 year .

    然后找到第一个和最后一个 首选 每个名称和位置 from to 分别地 然后将这些文档投影到 从…起 不一样。

    以下是此命令的结果

    {
        "_id" : {
            "name" : "bob",
            "location" : 90210
        },
        "from" : "vanilla",
        "to" : "chocolate",
        "from_to_eq" : false
    }
    

    希望这有帮助。

        2
  •  0
  •   sweaves    9 年前

    首先,我想你需要保留偏好的历史记录?如果没有,您可以简单地用每个人的新偏好更新现有文档,然后就可以上路了。

    如果您需要历史记录,您必须在单个文档中捕获Bob的所有首选项,或者您应该为Bob的每个首选项创建一个新文档。如果可能有很多首选项更新,那么将首选项推入数组是一种糟糕的模式设计,因为您不知道文档会增长到多大。

    这可以通过几种方式实现。

    您应该包含带有时间戳或版本的字段。例如:

    { name: 'bob', 
      location: '90210',
      pref: 'vanilla',
      drink: 'coffee',
      v: 1
    }
    

    下次bob更新首选项时,只需插入一个新文档,内容如下:

    { name: 'bob', 
      location: '90210',
      pref: 'vanilla',
      drink: 'coffee',
      v: 2
    }
    

    然后,当您查询最新的首选项时,只需执行以下操作:

    db.customers.find({name:'bob}).sortby({v:-1}).limit(1)
    

    这有利于查找最新的首选项,但不利于查找以前的首选项。当您为每个用户存储多个文档时,它还有相当多的额外数据。

    另一种方法可以是将当前偏好存储在字段中,然后将先前偏好存储在数组中:

    { name: 'bob', 
      location: '90210',
      pref: 'vanilla',
      drink: 'coffee',
      prev_pref: ['chocolate', 'syrup']
    }
    

    通过这种方式,您可以获得鲍勃当前的偏好以及他过去的偏好记录,只需使用一个简单的:

    db.customers.find({name:'bob'})
    

    现在是额外的部分-一旦首选项被更新,你是否需要做些什么,例如Bob更新他的首选项会在MongoDB中引发某种触发事件?这需要在应用程序中处理,因为mongodb既不支持触发器,也不支持更改通知API。