Mongodb 索引并向上插入mongo子文档

Mongodb 索引并向上插入mongo子文档,mongodb,insert,mongoose,upsert,subdocument,Mongodb,Insert,Mongoose,Upsert,Subdocument,我在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 th

我在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})

我查看了这篇文章和其他一些文章,但不知怎么的,它们都不起作用。我不知道这是我的问题还是蒙哥的问题。谢谢

我建议您重新考虑您的模式:

  • upsert
    应用于文档级别,这与架构的结构不太匹配。如果在
    lons
    数组中找不到匹配项,则希望推送到现有文档,而不是创建新文档

  • 文档(包括无限增长的数组)可能会导致频繁的文档移动和性能问题(请参阅:)

  • 您的模式不适用于地理空间索引(需要将经度/纬度对作为数组或嵌入文档)。我猜这对于您的用例并不重要,因为您正在确保一个正常的唯一索引,但它可能值得考虑

更好的模式(假设您不打算使用地理空间查询)是:

{
    lon: -74.0059,
    lat: 40.7127,
    uid: 3
}
有了这个修改后的模式,您的更新需求就更简单了

  • 集合将lat作为唯一索引,对于每个lat,lon索引也是唯一的
  • 您仍然希望确保索引唯一:

          db.zones.ensureIndex({'lat': 1, 'lon':1}, {unique: true})
    
    二,。如果此集合中存在(lat,lon)对,请更新子文档中的uid

    三,。如果本文档中存在(lat),请在lons子文档中插入(lon,uid)

    四,。如果(lat)文档不存在,请创建lat文档并执行2

    所有这些逻辑现在都可以通过
    upsert
    来处理:

    db.zones.update(
    
        // query criteria
        { lat: 40.7127, lon: -74.0060 },
    
        // update
        { $set: {
            uid: 3
        }},
    
        // options
        {
            upsert: true
        }
    )
    
    如果要在更新现有文档时保留
    uid
    ,还可以使用操作符(而不是
    $set
    ):


    我以前也在想这个。问题是,我将在lon和lat中分别拥有大约10k点和10k点,这意味着我将以这种方式创建100m个文档。这仍然是一个好的设计吗?当然!阅读我提到的博客文章。在这两种情况下,对于相同的LAT/长对,都有相同数量的索引条目,因此考虑索引的大小相同。但是,如果在每个
    lat
    文档中嵌入10k
    lon
    值的数组,则当文档超出其磁盘空间时,会对性能造成额外的影响(每次文档移动时,该文档的所有索引项也必须更新)如果您只需要检索文档中的一个点,服务器就必须将整个文档加载到RAM中。对于以这种方式创建的NxN文档,查询时间是O(1)还是O(N^2)?另外,你能为我推荐更多的查询资源吗?mongo的udpate费用?大O的东西?非常感谢你!!另外,我打算对NxN表做的是在其中插入一些uid,在完成N^2次插入之后,除了查询之外,我什么也不做(很长一段时间)。在这种情况下,您仍然认为NxN文档是一个好的设计吗?
    db.zones.update(
    
        // query criteria
        { lat: 40.7127, lon: -74.0060 },
    
        // update
        { $setOnInsert: {
            uid: 3
        }},
    
        // options
        {
            upsert: true
        }
    )