有没有办法让列表中的子文档在mongodb中有一个唯一的字段?
文件结构:
{
"_id" : "2013-08-13",
"hours" : [
{
"hour" : "23",
"file" : [
{
"date_added" : ISODate("2014-04-03T18:54:36.400Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.410Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.402Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.671Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
}
]
}
]
}
我想确保文档的hours.hour值在插入时具有唯一的项目。问题是小时是一个列表。你能用这种方式确保索引吗?
答案 0 :(得分:1)
索引不是确保嵌入式数组唯一性的工具,而是跨文档使用它们以确保某些字段不会在那里重复。
只要您可以确定要添加的内容与任何其他值没有任何区别,那么您可以使用$addToSet
运算符进行更新:
db.collection.update(
{ "_id": "2013-08-13", "hour": 23 },
{ "$addToSet": {
"hours.$.file": {
"date_added" : ISODate("2014-04-03T18:54:36.671Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
}
}}
)
因此,文档将不,因为已存在与目标数组中的精确值匹配的元素。如果内容不同(这意味着任何部分内容,则会添加新项目。
对于其他任何事情,您需要通过加载文档并检查数组元素来手动维护。假设一个具有完全相同时间戳的不同“文件名”。
现在回答问题我想指出架构设计存在的问题。
日期作为字符串是“可怕的”。你可能认为你需要它们,但你不需要它们。有关详细信息,请参阅聚合框架date operators。
您有嵌套数组,通常应避免使用。常见问题显示在positional $
运算符的文档中。这表示你只能在位置上获得一个匹配,而总是“顶级”数组。因此,除了如上所示添加内容之外的更新将很困难。
更好的架构模式是简单地执行此操作:
{
"date_added" : ISODate("2014-04-03T18:54:36.400Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.410Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.402Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.671Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
}
如果它在自己的集合中,那么您始终可以使用索引来确保唯一性。聚合框架可以根据需要细分日期部分和小时。
您必须将其作为另一个文档的一部分,然后尝试至少避免嵌套数组。这是可以接受的,但不像分隔条目那样灵活:
{
"_id" : "2013-08-13",
"hours" : {
"23": [
{
"date_added" : ISODate("2014-04-03T18:54:36.400Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.410Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.402Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
},
{
"date_added" : ISODate("2014-04-03T18:54:36.671Z"),
"name" : "1376434800_file_output_2014-03-10-09-27_44.csv"
}
]
}
}
这取决于您的预期用途,最后一次不允许您在一天内的几个小时内进行任何类型的聚合比较。不是以任何简单的方式。前者很容易做到这一点,你仍然可以轻松地按天和小时分解选择。
然后,再次,如果您只是附加信息,那么应该找到您现有的架构。但请注意可能的问题和替代方案。