索引并插入一个 mongo 子文档
Posted
技术标签:
【中文标题】索引并插入一个 mongo 子文档【英文标题】:Index and upsert a mongo subdocument 【发布时间】:2014-10-24 02:02:51 【问题描述】:我正在开发 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 的问题。谢谢!
【问题讨论】:
【参考方案1】:我建议您重新考虑您的架构:
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。如果此集合中存在 (lat, lon) 对,则更新子文档中的 uid
3。如果 (lat) 存在于该文档中,则在 lons 子文档中插入 (lon, uid)
4。如果 (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
)
【讨论】:
我之前也在考虑这个问题。问题是我将在 lon 中有大约 10k 点,在 lat 中有 10k 点,这意味着我将以这种方式创建 100m 文档。这还是一个好的设计吗? 绝对!阅读我在large embedded arrays 上引用的博文。在这两种情况下,对于唯一的纬度/经度对,您拥有相同数量的索引条目,因此将索引视为大致相同的大小。但是,如果您在每个lat
文档中嵌入了 10k lon
值的数组,则由于文档超出了磁盘空间(每次文档移动,该文档的所有索引条目也必须是更新),如果您只需要检索文档中的一个点,服务器必须将整个文档加载到 RAM 中。
我明白了。对于以这种方式创建的 NxN 文档,查询时间是 O(1) 还是 O(N^2) ?您还可以为我推荐一些更多的查询资源,更新 mongo 的费用吗?大O的东西?非常感谢!!
我打算对 NxN 表执行的操作是,我会在其中插入一些 uid,在完成 N^2 次插入后,除了查询(很长一段时间。 )。在这种情况下,您仍然认为 NxN 文档是一个好的设计吗?以上是关于索引并插入一个 mongo 子文档的主要内容,如果未能解决你的问题,请参考以下文章