2014-08-30 2 views
0

을 upsert 나는 다음과 같은 일을하고 싶습니다 :지수와 내가 몽고 작업 한 몽고의 하위 문서

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?과 일부는 있지만 어떻게 든 작동하지는 않습니다. 내 문제인지 아니면 몽구스 문제인지 나는 모른다. 감사!

답변

2

난 당신이 스키마를 재고 제안 :

  • upsert은 스키마 구성 방식과 잘 맞지 않는 문서 수준에서 적용됩니다. lons 배열에 일치하는 항목이 없으면 새 문서를 만드는 대신 기존 문서로 푸시하고 싶습니다. 문서 이동 및 성능 문제가 자주 발생할 수 있습니다 무제한의 성장과 배열을 포함

  • 문서 (참조 : Why shouldn't I embed large arrays in my documents?를)

  • 같은 위도/경도 쌍을 필요 지리 공간 색인 (에 적합하지 않습니다 스키마 배열 또는 삽입 된 문서). 일반적인 유니크 인덱스를 보장하기 때문에 유스 케이스에서는 중요하지 않다고 생각하지만, 고려해 볼만한 가치가있다.

더 나은 스키마 것이다 (당신은 지리 공간 쿼리를 사용하지 않는 가정) :이 개정 된 스키마와

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

, 당신의 갱신 요구 사항은 더 간단합니다.

  1. 은 고유 인덱스 LAT, 또한 경도 지수 위도 각각의 고유 한 컬렉션이있다
당신은 여전히 ​​고유 인덱스 확인 할

:

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

2.이 컬렉션에 if (lat, lon) 쌍이 존재하면 하위 문서

에서 uid를 업데이트하십시오.

3.이 문서에 if (lat)가 있으면 lons 하위 문서에 (lon, uid)를 삽입하십시오.

4.당신이 uid 업데이트 할 때를 보존하려면

db.zones.update(

    // query criteria 
    { lat: 40.7127, lon: -74.0060 }, 

    // update 
    { $set: { 
     uid: 3 
    }}, 

    // options 
    { 
     upsert: true 
    } 
) 

: (이 위도) 문서가 존재하지 않는 경우, 위도 문서를 작성하고 2

이 모든 로직은 이제 upsert에 의해 처리 될 수 할

db.zones.update(

    // query criteria 
    { lat: 40.7127, lon: -74.0060 }, 

    // update 
    { $setOnInsert: { 
     uid: 3 
    }}, 

    // options 
    { 
     upsert: true 
    } 
) 
+0

내가 전에 이것에 대해 생각하고 있었다 : 기존 문서, 당신은 또한 (대신 $set에) $setOnInsert 연산자를 사용할 수 있습니다. 문제는 제가 약 10k 포인트의 lon과 10k lat를 갖게 될 것이므로이 방법으로 100m 문서를 만들 수 있다는 것을 의미합니다. 여전히 좋은 디자인입니까? –

+0

확실히! [대형 임베디드 어레이] (http://askasya.com/post/largeembeddedarrays)에서 언급 한 블로그 게시물을 읽어보십시오. 두 경우 모두 고유 한 위도/경도 쌍에 대해 동일한 수의 색인 항목이 있으므로 색인을 거의 동일한 크기로 간주하십시오. 그러나 각'lat' 문서에 10k'lon' 값의 배열이 포함되어 있다면, 문서가 디스크에서 공간을 초과함에 따라 추가 성능이 저하됩니다 (문서가 움직일 때마다 해당 문서의 모든 색인 항목 또한 있어야합니다). 업데이트 됨) 문서의 한 점만 가져와야하는 경우 서버는 전체 문서를 RAM에로드해야합니다. – Stennie

+0

나는 본다. 이 방법으로 생성 된 NxN 문서는 질의 시간 O (1) 또는 O (N^2)입니까? 또한 질문에 대한 더 많은 리소스를 제안 해 주시겠습니까, 몽고에 대한 불필요한 비용? 큰 오 물건들? 대단히 감사합니다 !! –