我正在研究mongo,我想做以下事情:
when a set of (lat, lon, uid) comes in:
1. the collection has lat as unique index, also for each lat the lon index is unique
2. if (lat, lon) pair exists in this collection, update uid in the sub-document
3. if (lat) exists in this document , insert (lon, uid) in the lons sub-document
4. if (lat) document doesn't exist, create lat document and do 2
[{
"lat" : 1, (doc is unique by lat)
"lons" : [
{
"lon" : 2, (the subdocument is unique by lon)
"uid" : 3
},
{
"lon" : 3,
"uid" : 3
}
]
},
{
"lat" : 2,
"lons" : [
{
"lon" : 2,
"uid" : 4
}
]
}]
我尝试做以下事情,但显然它没有像我想象的那样工作。
db.zones.update({'lat': 90}, {$push: {lons: {'uid' : 0, 'lon': -18}}}, { upsert: true })
db.zones.ensureIndex({'lat': -1, 'lons.lon':1}, {unique: true})
我查看了这篇文章Can mongo upsert array data?以及其他一些帖子,但不管怎样它们都没有用。我不知道这是我的问题还是mongo问题。谢谢!
答案 0 :(得分:2)
我建议你重新考虑你的架构:
upsert
适用于文档级别,不能很好地适应架构的结构。如果在lons
数组中找不到匹配项,则您希望将其推送到现有文档而不是创建新文档。
包含无限增长数组的文档可能导致频繁的文档移动和性能问题(请参阅:Why shouldn't I embed large arrays in my documents?)
您的架构不适合地理空间索引(需要经度/纬度对作为数组或嵌入文档)。我猜这对你的用例来说并不重要,因为你确保了一个正常的唯一索引,但它可能值得考虑。
更好的架构(假设您不打算使用地理空间查询)将是:
{
lon: -74.0059,
lat: 40.7127,
uid: 3
}
使用此修订架构,您的更新要求更加简单。
- 该集合具有lat作为唯一索引,对于每个lat,lon索引也是唯一的
醇>
您仍然希望确保唯一索引:
db.zones.ensureIndex({'lat': 1, 'lon':1}, {unique: true})
2。 if(lat,lon)对存在于此集合中,请更新子文档中的uid
3。如果(lat)存在于此文档中,请在lons子文档中插入(lon,uid)
4。 if(lat)文档不存在,创建lat文档并执行2
所有这些逻辑现在都可以由upsert
处理:
db.zones.update(
// query criteria
{ lat: 40.7127, lon: -74.0060 },
// update
{ $set: {
uid: 3
}},
// options
{
upsert: true
}
)
如果您想在更新现有文档时保留uid
,还可以使用$setOnInsert
运算符(而不是$set
):
db.zones.update(
// query criteria
{ lat: 40.7127, lon: -74.0060 },
// update
{ $setOnInsert: {
uid: 3
}},
// options
{
upsert: true
}
)