我们假设我想跟踪网络上的计算机,这些计算机存储有关mac-address的信息,包括设备名称,端口名称,vlan编号和时间戳。 我可以定期从所有交换机中获取mac-address-table,解析它并将该数据转储到mongodb中。
问题是:如何为每个mac-address存储最后100个唯一条目。
上限集合是不行的,因为要做到这一点,我必须为每个mac创建单独的集合,这是个坏主意。
交换机和mac地址的数量可能会随着时间的推移而变化,并且可能会以不规则的间隔插入新数据。
我的另一个想法是编写一些查询,查找每个mac-address的第100个最旧条目的时间戳,并删除所有旧条目,并在每批插入后运行此查询。它可能有用,但看起来效率不高。
你有更好的想法吗?
答案 0 :(得分:2)
如何使用$ push运算符和$ slice修饰符将每个版本存储在数组中?
文档中有一些示例: http://docs.mongodb.org/manual/reference/operator/update/slice/
答案 1 :(得分:1)
我的另一个想法是编写一些查询,查找每个mac-address的第100个最旧条目的时间戳,并删除所有旧条目,并在每批插入后运行此查询。它可能有用,但看起来效率不高。
这对我来说听起来不错。为此使用循环缓冲区可能更清晰:
{
mac : "AA:AA:AA:AA:AA",
entryPointer : 2, // pointer of the next entry to be written
lastEntries : [
{ "ip" : "127.0.0.1", "service" : "foo", ts : ISODate(...), ... },
{ "ip" : "127.0.0.1", "service" : "foo", ts : ISODate(...), ... },
{ "ip" : "255.255.255.255", "service" : "longestProbableServiceName",
ts : ISODate(0001-01-01), ... }
...
{ "ip" : "255.255.255.255", "service" : "longestProbableServiceName",
ts : ISODate(0001-01-01), ... }
]
}
更新必须增加指针并覆盖指针%100给出的数组中的位置。如图所示,预先分配数组中的内存将有助于避免碎片和重新分配开销。
正如您所指出的,可以使用$slice
and $push
:
db.foo.update(
{ mac : "AA:AA:AA..." },
{
$push: {
lastEntries : {
$each: [ { "ip" : "012.002.003.012", ... } ],
$slice: -100
}
}
}
)
预先填充数组还有一个优势,即最近的条目始终位于最后一个位置。