복붙노트

[MONGODB] MongoDB의 쿼리 도움말 - 하위 오브젝트의 모든 키의 값에 대한 쿼리

MONGODB

MongoDB의 쿼리 도움말 - 하위 오브젝트의 모든 키의 값에 대한 쿼리

나는 특정 값과 일치하는 일에 어떤 키를 가지고있는 문서를 확인하려면이 컬렉션 쿼리를 수행하고자합니다. 이것이 가능한가?

내가 좋아하는 문서의 컬렉션이 있습니다 :

{
    "things": {
        "thing1": "red",
        "thing2": "blue",
        "thing3": "green"
    }
}

편집 : 간결함을 위해

해결법

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

    1.당신이 실제로 MongoDB를 합리적인 쿼리를 수행 할 수 있도록 내가 스키마 변경을 건의 할 것입니다.

    당신이 실제로 MongoDB를 합리적인 쿼리를 수행 할 수 있도록 내가 스키마 변경을 건의 할 것입니다.

    에서:

    {
        "userId": "12347",
        "settings": {
            "SettingA": "blue",
            "SettingB": "blue",
            "SettingC": "green"
        }
    }
    

    에:

    {
        "userId": "12347",
        "settings": [
            { name: "SettingA", value: "blue" },
            { name: "SettingB", value: "blue" },
            { name: "SettingC", value: "green" }
        ]    
    }
    

    그런 다음 "settings.value"인덱스를 수 있고, 같은 쿼리를 수행합니다

    db.settings.ensureIndex({ "settings.value" : 1})
    
    db.settings.find({ "settings.value" : "blue" })
    

    이 배열로 설정 목록을 설정 이름을 이동하고 완전히 색인 필드에 값을 설정, 저장으로의 변화는 정말 ... 간단하다.

    스키마를 변경할 수없는 경우, 당신은 JohnnyHK의 솔루션 @ 시도 할 수 있지만,이 성능면에서 최악의 경우 기본적으로 있다고 경고하고이 인덱스를 효율적으로 작동하지 않습니다.

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

    2.당신은 키가 될 것입니다 무엇을 모르는 당신이 상호 작용해야하는 경우에, 당신은 사용하는 데 필요한 (악명 높은 성능 도전) $ 여기서 이렇게 (쉘에서)와 같은 연산자

    당신은 키가 될 것입니다 무엇을 모르는 당신이 상호 작용해야하는 경우에, 당신은 사용하는 데 필요한 (악명 높은 성능 도전) $ 여기서 이렇게 (쉘에서)와 같은 연산자

    db.test.find({$where: function() { 
        for (var field in this.settings) { 
            if (this.settings[field] == "red") return true;
        }
        return false;
    }})
    

    컬렉션이 큰 경우에, 이것은 당신의 목적을 위해 너무 느린 수 있지만, 키 당신의 세트를 알 수없는 경우가 유일한 옵션입니다.

    MongoDB를 3.6 업데이트

    당신은 지금 어디 $ objectToArray 집계 연산자를 사용하여 $없이이 작업을 수행 할 수 있습니다

    db.test.aggregate([
      // Project things as a key/value array, along with the original doc
      {$project: {
        array: {$objectToArray: '$things'},
        doc: '$$ROOT'
      }},
    
      // Match the docs with a field value of 'red'
      {$match: {'array.v': 'red'}},
    
      // Re-project the original doc
      {$replaceRoot: {newRoot: '$doc'}}
    ])
    
  3. ==============================

    3.슬프게도, 이전 답변을 아무도 몽고는 배열이나 중첩 된 객체에 중첩 된 값을 포함 할 수 있다는 사실을 해결합니다.

    슬프게도, 이전 답변을 아무도 몽고는 배열이나 중첩 된 객체에 중첩 된 값을 포함 할 수 있다는 사실을 해결합니다.

    이는 올바른 QUERY입니다

    {$where: function() {
        var deepIterate = function  (obj, value) {
            for (var field in obj) {
                if (obj[field] == value){
                    return true;
                }
                var found = false;
                if ( typeof obj[field] === 'object') {
                    found = deepIterate(obj[field], value)
                    if (found) { return true; }
                }
            }
            return false;
        };
        return deepIterate(this, "573c79aef4ef4b9a9523028f")
    }}
    

    질의는 모든 중첩 요소에 반복되며, 값과 키가 발견 될 때까지 모든 것을 반복하는 수단이 '물체'를 반환 배열 또는 중첩 된 객체에 대해서 typeof 전화입니다.

    당신은 중첩 된 값으로 이전 답변을 확인하실 수 있습니다 원하는에서 결과까지 될 것입니다.

    그들을 일치하려고 한 모든 메모리 분야의 일을 반복해야하기 때문에 전체 개체를 Stringifying하면 성능에 히트입니다. 그리고 램 메모리에 문자열로 객체의 복사본 (더 많은 RAM과 기능 컨텍스트가 이미로드 된 객체를 가지고 있기 때문에 느린 쿼리 사용하기 때문에 모두 비효율적)을 만듭니다.

    자체 OBJECTID, 문자열로 작업 할 수 있습니다 쿼리, INT 및 기본 자바 스크립트 원하는 입력합니다.

  4. from https://stackoverflow.com/questions/19802502/mongodb-query-help-query-on-values-of-any-key-in-a-sub-object by cc-by-sa and MIT license