복붙노트

[MONGODB] 배열 필드가 비어 있지 않은 경우 MongoDB를 기록 찾기

MONGODB

배열 필드가 비어 있지 않은 경우 MongoDB를 기록 찾기

내 기록의 모든 필드는 "사진"이라고했다. 이 필드는 문자열의 배열이다.

이 배열이 비어 있지 어디 이제 새로운 10 개 개의 레코드를 원한다.

나는 주위 검색 좀했지만, 이상하게 나는 이것에 많이 발견하지 않았습니다. 어디서 옵션 $로 읽었습니다,하지만 난 더 나은 솔루션이 기본 기능에, 그리고 경우입니다 방법 느린 궁금 해서요.

그리고 그렇다하더라도, 그것은 작동하지 않습니다

ME.find({$where: 'this.pictures.length > 0'}).sort('-created').limit(10).execFind()

아무 것도 반환하지 않습니다. 길이 비트없이 this.pictures두면 작업을 수행하지만, 그것은 또한 물론, 빈 레코드를 반환합니다.

해결법

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

    1.당신은 또한 키가없는 문서가있는 경우, 당신은 사용할 수 있습니다 :

    당신은 또한 키가없는 문서가있는 경우, 당신은 사용할 수 있습니다 :

    ME.find({ pictures: { $exists: true, $not: {$size: 0} } })
    

    $ 크기가 포함되어있는 경우 MongoDB를 인덱스를 사용하지 않는, 그래서 여기에 더 나은 솔루션입니다 :

    ME.find({ pictures: { $exists: true, $ne: [] } })
    

    MongoDB를 2.6 출시 된 이후, 당신은 운영자 $ GT는 비교 할 수 있지만 (이 대답에서 자세한 것을 설명을 찾을 수 있습니다) 예기치 않은 결과가 발생할 수 있습니다 :

    ME.find({ pictures: { $gt: [] } })
    
  2. ==============================

    2.더 특히 MongoDB를 문서에서 찾고, 함께 비트를 수수께끼 일부 후이 대답했다 :

    더 특히 MongoDB를 문서에서 찾고, 함께 비트를 수수께끼 일부 후이 대답했다 :

    ME.find({pictures: {$exists: true, $not: {$size: 0}}})
    
  3. ==============================

    3.이것은 또한 당신을 위해 작동하지 않을 수 있습니다 :

    이것은 또한 당신을 위해 작동하지 않을 수 있습니다 :

    ME.find({'pictures.0': {$exists: true}});
    
  4. ==============================

    4.정확도와 성능 - 당신은 쿼리 두 가지에 관심. 염두에두고, 나는 MongoDB의의 v3.0.14에서 몇 가지 다른 방법을 시험했다.

    정확도와 성능 - 당신은 쿼리 두 가지에 관심. 염두에두고, 나는 MongoDB의의 v3.0.14에서 몇 가지 다른 방법을 시험했다.

    TL; DR이 db.doc.find ({{$ 하였다 : nums -Infinity를}})이며 가장 신속하고 신뢰성 (I는 테스트 MongoDB의 버전 적어도).

    편집 : 이것은 더 이상 MongoDB를의 V3.6에서 작동하지 않습니다! 잠재적 인 솔루션이 게시물 아래에있는 주석을 참조하십시오.

    나는 비어 있지 않은 목록 / O 목록 필드 w 1K 문서, 빈 목록 1K 워드 프로세서, 5 문서를 삽입.

    for (var i = 0; i < 1000; i++) { db.doc.insert({}); }
    for (var i = 0; i < 1000; i++) { db.doc.insert({ nums: [] }); }
    for (var i = 0; i < 5; i++) { db.doc.insert({ nums: [1, 2, 3] }); }
    db.doc.createIndex({ nums: 1 });
    

    나는이 충분하지 않은 규모의 I 아래의 테스트에서 나처럼 진지로 성능을 가지고하는 것입니다 인식하지만, 다양한 질의의 정확성 및 선택 쿼리 계획의 동작을 제공하기에 충분합니다.

    db.doc.find ({ 'nums'{ '$가 존재한다'는 true}}) (우리가 달성하려는 것에 대해) 잘못된 결과를 반환합니다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': {'$exists': true}}).count()
    1005
    

    --

    db.doc.find ({ 'nums.0'{ '$ 존재'는 true}}) 올바른 결과를 반환하지만 그것은 또한 느린 전체 컬렉션을 스캔 (설명에 통지 COLLSCAN 단계)를 사용합니다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums.0': {'$exists': true}}).count()
    5
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums.0': {'$exists': true}}).explain()
    {
      "queryPlanner": {
        "plannerVersion": 1,
        "namespace": "test.doc",
        "indexFilterSet": false,
        "parsedQuery": {
          "nums.0": {
            "$exists": true
          }
        },
        "winningPlan": {
          "stage": "COLLSCAN",
          "filter": {
            "nums.0": {
              "$exists": true
            }
          },
          "direction": "forward"
        },
        "rejectedPlans": [ ]
      },
      "serverInfo": {
        "host": "MacBook-Pro",
        "port": 27017,
        "version": "3.0.14",
        "gitVersion": "08352afcca24bfc145240a0fac9d28b978ab77f3"
      },
      "ok": 1
    }
    

    --

    db.doc.find ({ 'nums가'{$가 존재 : 사실, $있다 : { '$ 크기': 0}}}) 잘못된 결과를 반환합니다. 때문에 잘못된 인덱스의의는 어떤 문서를 진행하지 스캔합니다. 그것은 가능성이 정확하지만, 인덱스없이 속도가 느려집니다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $gt: { '$size': 0 }}}).count()
    0
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $gt: { '$size': 0 }}}).explain('executionStats').executionStats.executionStages
    {
      "stage": "KEEP_MUTATIONS",
      "nReturned": 0,
      "executionTimeMillisEstimate": 0,
      "works": 2,
      "advanced": 0,
      "needTime": 0,
      "needFetch": 0,
      "saveState": 0,
      "restoreState": 0,
      "isEOF": 1,
      "invalidates": 0,
      "inputStage": {
        "stage": "FETCH",
        "filter": {
          "$and": [
            {
              "nums": {
                "$gt": {
                  "$size": 0
                }
              }
            },
            {
              "nums": {
                "$exists": true
              }
            }
          ]
        },
        "nReturned": 0,
        "executionTimeMillisEstimate": 0,
        "works": 1,
        "advanced": 0,
        "needTime": 0,
        "needFetch": 0,
        "saveState": 0,
        "restoreState": 0,
        "isEOF": 1,
        "invalidates": 0,
        "docsExamined": 0,
        "alreadyHasObj": 0,
        "inputStage": {
          "stage": "IXSCAN",
          "nReturned": 0,
          "executionTimeMillisEstimate": 0,
          "works": 1,
          "advanced": 0,
          "needTime": 0,
          "needFetch": 0,
          "saveState": 0,
          "restoreState": 0,
          "isEOF": 1,
          "invalidates": 0,
          "keyPattern": {
            "nums": 1
          },
          "indexName": "nums_1",
          "isMultiKey": true,
          "direction": "forward",
          "indexBounds": {
            "nums": [
              "({ $size: 0.0 }, [])"
            ]
          },
          "keysExamined": 0,
          "dupsTested": 0,
          "dupsDropped": 0,
          "seenInvalidated": 0,
          "matchTested": 0
        }
      }
    }
    

    --

    db.doc.find ({ 'nums가'{$가 존재 : 사실, $ 없습니다 : { '$ 크기': 0}}}) 올바른 결과를 반환하지만 성능이 좋지 않습니다. 그것은 기술적으로 인덱스 스캔을 수행,하지만 여전히 모든 문서를 전진하고) 그들을 통해 필터에있다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $not: { '$size': 0 }}}).count()
    5
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $not: { '$size': 0 }}}).explain('executionStats').executionStats.executionStages
    {
      "stage": "KEEP_MUTATIONS",
      "nReturned": 5,
      "executionTimeMillisEstimate": 0,
      "works": 2016,
      "advanced": 5,
      "needTime": 2010,
      "needFetch": 0,
      "saveState": 15,
      "restoreState": 15,
      "isEOF": 1,
      "invalidates": 0,
      "inputStage": {
        "stage": "FETCH",
        "filter": {
          "$and": [
            {
              "nums": {
                "$exists": true
              }
            },
            {
              "$not": {
                "nums": {
                  "$size": 0
                }
              }
            }
          ]
        },
        "nReturned": 5,
        "executionTimeMillisEstimate": 0,
        "works": 2016,
        "advanced": 5,
        "needTime": 2010,
        "needFetch": 0,
        "saveState": 15,
        "restoreState": 15,
        "isEOF": 1,
        "invalidates": 0,
        "docsExamined": 2005,
        "alreadyHasObj": 0,
        "inputStage": {
          "stage": "IXSCAN",
          "nReturned": 2005,
          "executionTimeMillisEstimate": 0,
          "works": 2015,
          "advanced": 2005,
          "needTime": 10,
          "needFetch": 0,
          "saveState": 15,
          "restoreState": 15,
          "isEOF": 1,
          "invalidates": 0,
          "keyPattern": {
            "nums": 1
          },
          "indexName": "nums_1",
          "isMultiKey": true,
          "direction": "forward",
          "indexBounds": {
            "nums": [
              "[MinKey, MaxKey]"
            ]
          },
          "keysExamined": 2015,
          "dupsTested": 2015,
          "dupsDropped": 10,
          "seenInvalidated": 0,
          "matchTested": 0
        }
      }
    }
    

    --

    db.doc.find ({ 'nums가'{$가 존재 : 사실, $ NE는 : []}}) 올바른 결과를 반환하고 약간 빠르지 만 성능은 아직 적합하지 않습니다. 그것은 단지 기존의 목록 필드에 문서를 전진 IXSCAN를 사용하지만, 다음 빈 목록 하나 하나를 필터링 할 수 있습니다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $ne: [] }}).count()
    5
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $exists: true, $ne: [] }}).explain('executionStats').executionStats.executionStages
    {
      "stage": "KEEP_MUTATIONS",
      "nReturned": 5,
      "executionTimeMillisEstimate": 0,
      "works": 1018,
      "advanced": 5,
      "needTime": 1011,
      "needFetch": 0,
      "saveState": 15,
      "restoreState": 15,
      "isEOF": 1,
      "invalidates": 0,
      "inputStage": {
        "stage": "FETCH",
        "filter": {
          "$and": [
            {
              "$not": {
                "nums": {
                  "$eq": [ ]
                }
              }
            },
            {
              "nums": {
                "$exists": true
              }
            }
          ]
        },
        "nReturned": 5,
        "executionTimeMillisEstimate": 0,
        "works": 1017,
        "advanced": 5,
        "needTime": 1011,
        "needFetch": 0,
        "saveState": 15,
        "restoreState": 15,
        "isEOF": 1,
        "invalidates": 0,
        "docsExamined": 1005,
        "alreadyHasObj": 0,
        "inputStage": {
          "stage": "IXSCAN",
          "nReturned": 1005,
          "executionTimeMillisEstimate": 0,
          "works": 1016,
          "advanced": 1005,
          "needTime": 11,
          "needFetch": 0,
          "saveState": 15,
          "restoreState": 15,
          "isEOF": 1,
          "invalidates": 0,
          "keyPattern": {
            "nums": 1
          },
          "indexName": "nums_1",
          "isMultiKey": true,
          "direction": "forward",
          "indexBounds": {
            "nums": [
              "[MinKey, undefined)",
              "(undefined, [])",
              "([], MaxKey]"
            ]
          },
          "keysExamined": 1016,
          "dupsTested": 1015,
          "dupsDropped": 10,
          "seenInvalidated": 0,
          "matchTested": 0
        }
      }
    }
    

    --

    db.doc.find ({ 'nums'$ {GT를 []}})의 INDEX는 IT 예기치 않은 결과를 줄 수도 USED DEPENDING 위험한 때문이다. 그 때문에 어떤 문서를 전진하지 잘못된 인덱스 스캔의입니다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $gt: [] }}).count()
    0
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $gt: [] }}).hint({ nums: 1 }).count()
    0
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $gt: [] }}).hint({ _id: 1 }).count()
    5
    
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $gt: [] }}).explain('executionStats').executionStats.executionStages
    {
      "stage": "KEEP_MUTATIONS",
      "nReturned": 0,
      "executionTimeMillisEstimate": 0,
      "works": 1,
      "advanced": 0,
      "needTime": 0,
      "needFetch": 0,
      "saveState": 0,
      "restoreState": 0,
      "isEOF": 1,
      "invalidates": 0,
      "inputStage": {
        "stage": "FETCH",
        "filter": {
          "nums": {
            "$gt": [ ]
          }
        },
        "nReturned": 0,
        "executionTimeMillisEstimate": 0,
        "works": 1,
        "advanced": 0,
        "needTime": 0,
        "needFetch": 0,
        "saveState": 0,
        "restoreState": 0,
        "isEOF": 1,
        "invalidates": 0,
        "docsExamined": 0,
        "alreadyHasObj": 0,
        "inputStage": {
          "stage": "IXSCAN",
          "nReturned": 0,
          "executionTimeMillisEstimate": 0,
          "works": 1,
          "advanced": 0,
          "needTime": 0,
          "needFetch": 0,
          "saveState": 0,
          "restoreState": 0,
          "isEOF": 1,
          "invalidates": 0,
          "keyPattern": {
            "nums": 1
          },
          "indexName": "nums_1",
          "isMultiKey": true,
          "direction": "forward",
          "indexBounds": {
            "nums": [
              "([], BinData(0, ))"
            ]
          },
          "keysExamined": 0,
          "dupsTested": 0,
          "dupsDropped": 0,
          "seenInvalidated": 0,
          "matchTested": 0
        }
      }
    }
    

    --

    db.doc.find ({ 'nums.0': {$있다 : -Infinity는}}) 올바른 결과를 반환하지만 나쁜 성능 (전체 수집 스캔을 사용)이있다.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums.0': { $gt: -Infinity }}).count()
    5
    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums.0': { $gt: -Infinity }}).explain('executionStats').executionStats.executionStages
    {
      "stage": "COLLSCAN",
      "filter": {
        "nums.0": {
          "$gt": -Infinity
        }
      },
      "nReturned": 5,
      "executionTimeMillisEstimate": 0,
      "works": 2007,
      "advanced": 5,
      "needTime": 2001,
      "needFetch": 0,
      "saveState": 15,
      "restoreState": 15,
      "isEOF": 1,
      "invalidates": 0,
      "direction": "forward",
      "docsExamined": 2005
    }
    

    --

    db.doc.find ({ 'nums은'{$있다 : -Infinity는}}) 놀랍게도, 이것은 매우 잘 작동합니다! 그것은 바로 결과를 제공하며 인덱스 스캔 단계에서 5 문서를 전진, 빨리.

    MacBook-Pro(mongod-3.0.14) test> db.doc.find({'nums': { $gt: -Infinity }}).explain('executionStats').executionStats.executionStages
    {
      "stage": "FETCH",
      "nReturned": 5,
      "executionTimeMillisEstimate": 0,
      "works": 16,
      "advanced": 5,
      "needTime": 10,
      "needFetch": 0,
      "saveState": 0,
      "restoreState": 0,
      "isEOF": 1,
      "invalidates": 0,
      "docsExamined": 5,
      "alreadyHasObj": 0,
      "inputStage": {
        "stage": "IXSCAN",
        "nReturned": 5,
        "executionTimeMillisEstimate": 0,
        "works": 15,
        "advanced": 5,
        "needTime": 10,
        "needFetch": 0,
        "saveState": 0,
        "restoreState": 0,
        "isEOF": 1,
        "invalidates": 0,
        "keyPattern": {
          "nums": 1
        },
        "indexName": "nums_1",
        "isMultiKey": true,
        "direction": "forward",
        "indexBounds": {
          "nums": [
            "(-inf.0, inf.0]"
          ]
        },
        "keysExamined": 15,
        "dupsTested": 15,
        "dupsDropped": 10,
        "seenInvalidated": 0,
        "matchTested": 0
      }
    }
    
  5. ==============================

    5.2.6 릴리스부터이 작업을 수행하는 또 다른 방법은 빈 배열에 필드를 비교하는 것입니다 :

    2.6 릴리스부터이 작업을 수행하는 또 다른 방법은 빈 배열에 필드를 비교하는 것입니다 :

    ME.find({pictures: {$gt: []}})
    

    쉘에서 그것을 테스트 :

    > db.ME.insert([
    {pictures: [1,2,3]},
    {pictures: []},
    {pictures: ['']},
    {pictures: [0]},
    {pictures: 1},
    {foobar: 1}
    ])
    
    > db.ME.find({pictures: {$gt: []}})
    { "_id": ObjectId("54d4d9ff96340090b6c1c4a7"), "pictures": [ 1, 2, 3 ] }
    { "_id": ObjectId("54d4d9ff96340090b6c1c4a9"), "pictures": [ "" ] }
    { "_id": ObjectId("54d4d9ff96340090b6c1c4aa"), "pictures": [ 0 ] }
    

    사진 적어도 하나 개의 배열 요소를 가지고 있으며, 제외 사진 중 하나는 하늘의 배열이 아니라 배열 또는 누락 된 워드 프로세서를 어디 제대로 문서를 포함 그래서.

  6. ==============================

    6.이 작업을 달성하기 위해 다음 중 하나를 사용할 수 있습니다. 둘 다 또한 그들의 요청 키가없는 개체에 대한 결과를 반환하지 돌봐 :

    이 작업을 달성하기 위해 다음 중 하나를 사용할 수 있습니다. 둘 다 또한 그들의 요청 키가없는 개체에 대한 결과를 반환하지 돌봐 :

    db.video.find({pictures: {$exists: true, $gt: {$size: 0}}})
    db.video.find({comments: {$exists: true, $not: {$size: 0}}})
    
  7. ==============================

    7.

    { $where: "this.pictures.length > 1" }
    

    $ 어디에 사용할 배열 필드의 크기를 반환 this.field_name.length를 통과 수에 비교하여 확인한다. 임의의 어레이가 배열 크기보다 가치가있는 경우 배열 필드 길이보다 하나가 매우 모두 그것이 그 어레이의 일부 데이터를 의미하며, 적어도 1이어야

  8. ==============================

    8.

    ME.find({pictures: {$type: 'array', $ne: []}})
    

    대신 $ 유형의 4 : 4 : '배열'이전 3.2에 MongoDB의 버전을 사용하는 경우, $ 유형을 사용합니다. 이 솔루션도 $ 크기를 사용하지 않도록주의 때문에 인덱스 문제 ( "쿼리는 쿼리의 $ 크기 부분에 대한 인덱스를 사용할 수 없습니다")가 없다

    이 (허용 대답)를 포함하여 다른 솔루션 :

    그들은 예를 들어, 문서의 경우에도를 반환하기 때문에 잘못, '사진'널 (null), 정의되지 않은, 0 등입니다

  9. ==============================

    9.$ elemMatch 연산자를 사용하여 문서에 따라

    $ elemMatch 연산자를 사용하여 문서에 따라

    $ elemMatches는 값이 배열인지 확인하게하고 비어 있지 않은지. 쿼리는 같은 것이다 그래서

    ME.find ({사진 : {$ elemMatch : {$가 존재 : TRUE}}})

    이 코드의 추신 변형은 MongoDB를 대학의 M121 과정에서 발견된다.

  10. ==============================

    10.또한 몽고 연산자 $가 존재하는 도우미 메서드가 이상 존재 사용할 수 있습니다

    또한 몽고 연산자 $가 존재하는 도우미 메서드가 이상 존재 사용할 수 있습니다

    ME.find()
        .exists('pictures')
        .where('pictures').ne([])
        .sort('-created')
        .limit(10)
        .exec(function(err, results){
            ...
        });
    
  11. ==============================

    11.

    ME.find({pictures: {$exists: true}}) 
    

    간단한 것과,이 날 위해 일했습니다.

  12. from https://stackoverflow.com/questions/14789684/find-mongodb-records-where-array-field-is-not-empty by cc-by-sa and MIT license