0

I was working on mongo and I'd like to do the following things:

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
        }
    ]
}]

I tried to do the following things but apparently it's not working as what I imagined.

db.zones.update({'lat': 90}, {$push: {lons: {'uid' : 0, 'lon': -18}}}, { upsert: true })
db.zones.ensureIndex({'lat': -1, 'lons.lon':1}, {unique: true})

I checked this post Can mongo upsert array data? and some others but somehow none of them is working. I don't know if it's my problem or mongo problem. Thanks!

4

1 回答 1

2

我建议您重新考虑您的架构:

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

  • 包含无限增长的数组的文档可能会导致频繁的文档移动和性能问题(请参阅:为什么不应该在我的文档中嵌入大型数组?

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

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

{
    lon: -74.0059,
    lat: 40.7127,
    uid: 3
}

使用此修改后的架构,您的更新要求将更加直接。

  1. 该集合具有 lat 作为唯一索引,对于每个 lat,lon 索引也是唯一的

您仍然希望确保唯一索引:

      db.zones.ensureIndex({'lat': 1, 'lon':1}, {unique: true})

2.如果该集合中存在(lat, lon) pair,则更新子文档中的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
    }
)
于 2014-08-30T12:34:40.693 回答