2017-01-16 2 views
1

저는 Personal.FirstName 필드와 Personal.Surname 필드를 가진 문서가있는 MongoDB 컬렉션을 가지고 있습니다. 일부 문서는 엉망이되어 두 필드의 성을 모두 가지고 있습니다. 예를 들어 Personal.FirstName = 'John Doe'및 Personal.Surname = 'John Doe'가있는 문서가 있습니다.mongodb에서 문자열 필드를 업데이트하고 문자열 값을 조작하는 방법은 무엇입니까?

나는 다음을 수행하는 몽고 업데이트 문을 작성하려는 :

  • 는 모든 문서를 찾기 개인 부분을 가지고있는 모든 문서를 찾아 어디 Personal.FirstName == 개인. 성
  • 업데이트 Personal.FirstName는 공간 후에 Personal.Surname 단지 두 번째 부분으로 공간
  • 업데이트 Personal.Surname 전에 Personal.FirstName 단지 첫 번째 부분이 될

mongo update 문에서 가능합니까? 나는 mongo를 처음 사용하고 있으며 쿼리하는 방법에 대해 거의 모릅니다.

편집 : 여기

{ 
    "_id" : LUUID("fcd140b1-ec0f-0c49-aa79-fed00899290e"), 
    "Personal" : { 
     "FirstName" : "John Doe", 
     "Surname" : "John Doe" 
    } 
} 
+0

질문을 편집하여 문서 구조를 보여주는 컬렉션의 샘플 문서를 보여줄 수 있습니까? – chridam

+0

물론, 예제 문서를 추가했습니다. –

답변

1

는 단일 쿼리에서이 작업을 수행 할 수 없습니다 예를 들어 문서입니다,하지만 당신은이 같은 결과를 반복하여이 작업을 수행 할 수 있습니다 :

db.name.find({$and: [{Personal: {$exists: true}}, {$where: "this.Personal.FirstName == this.Personal.Surname"}]}).forEach(function(e,i){ 
    var parts = e.Personal.FirstName.split(" "); 
    e.Personal.FirstName = parts[0]; 
    e.Personal.Surname = parts[1]; 
    db.name.save(e); 
}) 

결과 :

{ "_id" : "fcd140b1-ec0f-0c49-aa79-fed00899290e", "Personal" : { "FirstName" : "John", "Surname" : "Doe" } } 
+0

robomongo에서 다른 쿼리를 실행하는 것처럼 이것을 실행할 수 있습니까? 나는 robomong에서 그것을 실행 해 보았습니다. 스크립트가 잘 실행되고 실행하는 데 1 초가 걸렸습니다. 그리고 제 컬렉션에는 여전히 FirstName == 성함을 가진 많은 문서가 있습니다. 성함 –

+0

@CoreyBurnett 네, 할 수 있습니다. 올바른 컬렉션 이름을 사용해야합니다. 여기에 "이름"을 사용했지만 컬렉션에 다른 이름이 있다고 생각합니다. – felix

+0

고마워요. 그것은 작동하는 것 같습니다. 그러나 일치하는 모든 레코드를 실행할 때이를 수정하지 않는 것 같습니다. 한 번에 특정 숫자 만하는 것처럼 보입니다. robomongo가 일치하는 모든 레코드를 업데이트 할 수있는 방법이 있습니까? –

0

아이디어는 문서 th를 필터링하여 컬렉션의 문서 중 일부를 가져 오는 것입니다. 지정된 기준에 일치합니다. 부분 집합을 얻으면 목록을 반복하고 루프 내에서 각 문서 을 업데이트합니다.

지금, 하위 집합을 얻기 위해, 당신은 find()$where 연산자를 사용하여 필터를하는 것보다 빠릅니다 집계 파이프 라인을 실행해야합니다. 다음과 같은 예를 들어 당신이 업데이트에 사용할 수있는 추가 필드를 만들 필터링 메커니즘 다음 $project 파이프 라인으로 $redact를 사용 aggregate() 작업을 가져 가라. 결과를 포함하는 aggregate() 방법에서 커서가 다음의 forEach() 방법으로 반복 될 및 이후 일부에서 문서에 컬렉션을 업데이트 할 수 있습니다 다음 으로 집계 프레임 워크를 사용

db.collection.aggregate([ 
    { 
     "$redact": { 
      "$cond": [ 
       { 
        "$and": [ 
         { "$eq": [ "$Personal.FirstName", "$Personal.Surname" ] }, 
         { 
          "$gt": [ 
           { 
            "$size": { 
             "$split": ["$Personal.FirstName", " "] 
            } 
           }, 
           0 
          ] 
         } 
        ] 
       }, 
       "$$KEEP", 
       "$$PRUNE" 
      ] 
     } 
    }, 
    { 
     "$project": { 
      "FirstName": { 
       "$arrayElemAt": [ 
        { "$split": ["$Personal.FirstName", " "] }, 
        0 
       ] 
      }, 
      "Surname": { 
       "$arrayElemAt": [ 
        { "$split": ["$Personal.FirstName", " "] }, 
        1 
       ] 
      } 
     } 
    } 
]).forEach(function(doc) { 
    db.collection.updateOne(
     { "_id": doc._id }, 
     { 
      "$set": { 
       "Personal.FirstName": doc.FirstName, 
       "Personal.Surname": doc.Surname, 
      } 
     } 
    ) 
}) 

$redact 파이프 라인 연산자를 사용하면 $cond 연산자를 사용하여 논리 조건을 처리 할 수 ​​있으며 특수 작업 $$KEEP은 논리적 조건이 참인 문서를 "보관"하거나 $$PRUNE은 조건이 거짓 인 문서를 "제거"합니다.

이 성능 개선해야 크게 $redact 운전자는 수, 자바 스크립트 엔진은 모든 문서에 자바 스크립트 코드를 평가하기 위해 호출하는 $where 연산자와 쿼리 작업 동안 MongoDB를의 기본 연산자를 사용하며, 각각의 상태를 확인하기 때문에 MongoDB를가 $where 표현하기 전에 비 $where 쿼리 작업을 평가하고 비 $where 쿼리 문은 인덱스를 사용할 수 있습니다로 매우 느리게합니다.

관련 문제