복붙노트

[MONGODB] MongoDB를 맵리 듀스에서 어떻게 값 개체를 평평하게 할 수 있습니까?

MONGODB

MongoDB를 맵리 듀스에서 어떻게 값 개체를 평평하게 할 수 있습니까?

아파치 로그 파일을 분석하여 MongoDB를 사용하는 것을 시도하고있다. 나는 아파치 액세스 로그에서 영수증 수집을 만들었습니다. 여기 내 모델 모양을의 요약 된 요약이다 :

db.receipts.findOne()
{
    "_id" : ObjectId("4e57908c7a044a30dc03a888"),
    "path" : "/videos/1/show_invisibles.m4v",
    "issued_at" : ISODate("2011-04-08T00:00:00Z"),
    "status" : "200"
}

나는 맵리 듀스 기능을 작성한 그룹 그 issued_at 날짜 필드의 모든 데이터입니다. 이 요청의 총 수를 요약하고 각각의 고유 한 경로에 대한 요청의 수의 고장을 제공합니다. 여기에 출력 외모가 좋아의 예입니다 :

db.daily_hits_by_path.findOne()
{
    "_id" : ISODate("2011-04-08T00:00:00Z"),
    "value" : {
        "count" : 6,
        "paths" : {
            "/videos/1/show_invisibles.m4v" : {
                "count" : 2
            },
            "/videos/1/show_invisibles.ogv" : {
                "count" : 3
            },
            "/videos/6/buffers_listed_and_hidden.ogv" : {
                "count" : 1
            }
        }
    }
}

어떻게이 대신 같은 출력 모양을 만들 수 있습니다 :

{
    "_id" : ISODate("2011-04-08T00:00:00Z"),
    "count" : 6,
    "paths" : {
        "/videos/1/show_invisibles.m4v" : {
            "count" : 2
        },
        "/videos/1/show_invisibles.ogv" : {
            "count" : 3
        },
        "/videos/6/buffers_listed_and_hidden.ogv" : {
            "count" : 1
        }
    }
}

해결법

  1. ==============================

    1.그것은 현재 불가능하지만이 사건에 대한 투표를 제안했다 : https://jira.mongodb.org/browse/SERVER-2517.

    그것은 현재 불가능하지만이 사건에 대한 투표를 제안했다 : https://jira.mongodb.org/browse/SERVER-2517.

  2. ==============================

    2.이전 답변과 의견에서 최고의 촬영 :

    이전 답변과 의견에서 최고의 촬영 :

    db.items.find().hint({_id: 1}).forEach(function(item) {
        db.items.update({_id: item._id}, item.value);
    });
    

    http://docs.mongodb.org/manual/core/update/#replace-existing-document-with-new-document에서 "업데이트 인수는 필드 및 값 쌍 업데이트를 () 메소드는 _id 필드를 제외하고, 업데이트 인수 문서와 기존 문서를 대체합니다.이 포함 된 경우"

    당신은 $ 설정되지 않은 값을 둘 필요가 없습니다 그래서 없으며, 각 필드를 나열합니다.

    https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#cursor-snapshot에서 "MongoDB의 커서는 어떤 상황에서 한 번 이상 동일한 문서를 반환 할 수 있습니다. ...이 분야에 고유 인덱스 정도 쿼리를 두 번 이상 각 문서 더 이상 반환하지 것입니다. 쿼리 힌트 () 명시 적으로 강제하기 위해이 필드를 사용 쿼리는 해당 인덱스를 사용합니다. "

  3. ==============================

    3.AFAIK는 디자인 몽고의지도에 의해 "값 튜플"에 결과를 뱉어 줄이고 그 "출력 형식"을 구성합니다 아무것도 보지 못했다. 아마 마무리 () 메소드를 사용할 수 있습니다.

    AFAIK는 디자인 몽고의지도에 의해 "값 튜플"에 결과를 뱉어 줄이고 그 "출력 형식"을 구성합니다 아무것도 보지 못했다. 아마 마무리 () 메소드를 사용할 수 있습니다.

    당신은 사용하여 데이터를 재 형성하는 후 공정을 실행하려고 할 수

    results.find({}).forEach( function(result) {
      results.update({_id: result._id}, {count: result.value.count, paths: result.value.paths})
    });
    

    그래, 그 추한 보인다. 알아.

  4. ==============================

    4.당신은 수집 참조 댄의 코드를 수행 할 수 있습니다

    당신은 수집 참조 댄의 코드를 수행 할 수 있습니다

        function clean(collection) { 
          collection.find().forEach( function(result) {
          var value = result.value;
          delete value._id;     
          collection.update({_id: result._id}, value);     
          collection.update({_id: result.id}, {$unset: {value: 1}} ) } )};
    
  5. ==============================

    5.@ljonas의 그것과 유사한 접근하지만 하드 코드 문서 필드에 대한 필요가 없습니다 :

    @ljonas의 그것과 유사한 접근하지만 하드 코드 문서 필드에 대한 필요가 없습니다 :

    db.results.find().forEach( function(result) {
        var value = result.value;
        delete value._id;
        db.results.update({_id: result._id}, value);
        db.results.update({_id: result.id}, {$unset: {value: 1}} )
    } );
    
  6. ==============================

    6.모든 제안 된 솔루션은 최적의 거리가 멀다. 지금까지 할 수있는 가장 빠른 같은 것입니다 :

    모든 제안 된 솔루션은 최적의 거리가 멀다. 지금까지 할 수있는 가장 빠른 같은 것입니다 :

    var flattenMRCollection=function(dbName,collectionName) {
        var collection=db.getSiblingDB(dbName)[collectionName];
    
        var i=0;
        var bulk=collection.initializeUnorderedBulkOp();
        collection.find({ value: { $exists: true } }).addOption(16).forEach(function(result) {
            print((++i));
            //collection.update({_id: result._id},result.value);
    
            bulk.find({_id: result._id}).replaceOne(result.value);
    
            if(i%1000==0)
            {
                print("Executing bulk...");
                bulk.execute();
                bulk=collection.initializeUnorderedBulkOp();
            }
        });
        bulk.execute();
    };
    

    그런 다음 전화 : flattenMRCollection ( "보기 MyDB", "MyMRCollection")

    이것은 빠른 연속 업데이트를하는 것보다 길이다.

  7. ==============================

    7.빈센트의 대답을 실험하는 동안, 나는 몇 가지 문제를 발견했다. 당신이 foreach 루프 내에서 업데이트를 수행하는 경우 기본적으로,이 컬렉션의 끝에 문서를 이동하고 커서는 다시 문서 (예)에 도달 할 것이다. $ 스냅 샷을 사용하는 경우는 피할 수있다. 따라서, 나는 아래 자바 예제를 제공하고 있습니다.

    빈센트의 대답을 실험하는 동안, 나는 몇 가지 문제를 발견했다. 당신이 foreach 루프 내에서 업데이트를 수행하는 경우 기본적으로,이 컬렉션의 끝에 문서를 이동하고 커서는 다시 문서 (예)에 도달 할 것이다. $ 스냅 샷을 사용하는 경우는 피할 수있다. 따라서, 나는 아래 자바 예제를 제공하고 있습니다.

    final List<WriteModel<Document>> bulkUpdate = new ArrayList<>();
    
    // You should enable $snapshot if performing updates within foreach
    collection.find(new Document().append("$query", new Document()).append("$snapshot", true)).forEach(new Block<Document>() {
        @Override
        public void apply(final Document document) {
            // Note that I used incrementing long values for '_id'. Change to String if
            // you used string '_id's
            long docId = document.getLong("_id");
            Document subDoc = (Document)document.get("value");
            WriteModel<Document> m = new ReplaceOneModel<>(new Document().append("_id", docId), subDoc);
            bulkUpdate.add(m);
    
            // If you used non-incrementing '_id's, then you need to use a final object with a counter.
            if(docId % 1000 == 0 && !bulkUpdate.isEmpty()) {
                collection.bulkWrite(bulkUpdate);
                bulkUpdate.removeAll(bulkUpdate);
            }
        }
    });
    // Fixing bug related to Vincent's answer.
    if(!bulkUpdate.isEmpty()) {
        collection.bulkWrite(bulkUpdate);
        bulkUpdate.removeAll(bulkUpdate);
    }
    

    참고 :이 조각은 100,000 기록, 14 개 특성 (IMDB 데이터 세트) 내 컴퓨터에서 실행하는 데 7.4 초 평균 소요됩니다. 일괄 없이는 25.2 초 평균 소요됩니다.

  8. from https://stackoverflow.com/questions/7257989/in-mongodb-mapreduce-how-can-i-flatten-the-values-object by cc-by-sa and MIT license