source

"참이 아님"으로 부울 필드에 대한 쿼리(예: 거짓 또는 존재하지 않음)

manycodes 2023. 2. 25. 21:25
반응형

"참이 아님"으로 부울 필드에 대한 쿼리(예: 거짓 또는 존재하지 않음)

MongoDB 쿼리에서 매우 기본적인 것을 놓치고 있는 것이 확실합니다.이 간단한 조건을 얻을 수 없는 것 같습니다.

이 컬렉션을 고려합니다.

> db.tests.find()
{ "_id" : ObjectId("..."), "name" : "Test1" , "deleted" : true}
{ "_id" : ObjectId("..."), "name" : "Test2" , "deleted" : false}
{ "_id" : ObjectId("..."), "name" : "Test3" }

삭제되지 않은 아이템을 모두 문의하고 싶습니다.

"deleted" 플래그가 true로 설정된 항목을 찾는 방법을 알고 있습니다.

> db.tests.find({deleted:true})
{ "_id" : ObjectId("..."), "name" : "Test1" , "deleted" : true}

하지만 그렇지 않은 모든 항목을 찾으려면 어떻게 해야 합니까?"deleted"(예를 들어 위의 쿼리, 즉 다음 중 하나가 없는 항목은 모두 부정합니다)."deleted"필드 또는 가치 있는 것false

내가 추측해본 것 (웃지 말아주세요...)

> db.tests.find({$not : {deleted: true}})

(결과 없음)

> db.tests.find({$not : {$eq:{deleted:true}}})

오류: { "$err" : "paraming operator: $eq", "code" : 10068 }

> db.tests.find({deleted:{$not: true}})

오류: { "$err": "$not"을 잘못 사용", "code": 13041}

> db.tests.find({deleted:{$not: {$eq:true}}})

오류: { "$err": "$not"을 잘못 사용", "code": 13034 }

제가 무엇을 빠뜨리고 있나요?

db.tests.find({deleted: {$ne: true}})

어디에$ne"같지 않다"를 나타냅니다.(mongodb 연산자에 관한 문서)

완전성을 확보하기 위해 를 사용하는 방법도 있습니다.

db.test.find({deleted: {$in: [null, false]}})

포함하여null이 배열에서 docs를 끌어당겨서deleted필드가 없습니다.이 쿼리는 다음에 인덱스를 사용할 수 있습니다.{deleted: 1}현재 2.6.6 MongoDB 릴리즈에 포함되어 있습니다.

쟈니HK가 제일 잘 맞혔어요.$inselector는 가장 짧고 깨끗한 IMO입니다.

그러면 정확하게 "false" 또는 "non existent"가 테스트됩니다.색인화할 수 있습니다.

db.tests.find({$or:[{deleted:false},{deleted:{$exists:false}}]})

인덱스를 사용한 예.

((function(){
    print("creating collection 'testx' and inserting 50 trues, 50 falses, 50 non-existents");
    db.testx.drop();
    db.testx.ensureIndex({deleted:1});
    for (var i=0;i<50;i++){
        db.testx.insert({i:i,deleted:false});
    };
    for (var i=0;i<50;i++){
        db.testx.insert({i:i,deleted:true});
    };
    for (var i=0;i<50;i++){
        db.testx.insert({i:i});
    };
    var res0 = db.testx.find().explain();
    var res1 = db.testx.find({deleted:false}).explain();
    var res2 = db.testx.find({deleted:true}).explain();
    var res3 = db.testx.find({deleted:{$exists:false}}).explain();
    var res4 = db.testx.find({$or:[{deleted:false},{deleted:{$exists:false}}]}).explain();
    var res5 = db.testx.find({$or:[{deleted:true},{deleted:{$exists:false}}]}).explain();
    var res6 = db.testx.find({deleted:{$in:[false,null]}}).explain();
    print("res0: all objects                      ("+res0["n"]+" found, "+res0["nscannedObjects"]+" scanned)");
    print("res1: deleted is false                 ("+res1["n"]+" found, "+res1["nscannedObjects"]+" scanned)");
    print("res2: deleted is true                  ("+res2["n"]+" found, "+res2["nscannedObjects"]+" scanned)");
    print("res3: deleted is non-existent          ("+res3["n"]+" found, "+res3["nscannedObjects"]+" scanned)");
    print("res4: deleted is false or non-existent ("+res4["n"]+" found, "+res4["nscannedObjects"]+" scanned)");
    print("res5: deleted is true or non-existent  ("+res5["n"]+" found, "+res5["nscannedObjects"]+" scanned)");
    print("res6: deleted is in [false,null]       ("+res5["n"]+" found, "+res5["nscannedObjects"]+" scanned)");
})())

이것은 인쇄될 것입니다.

creating collection 'testx' and inserting 50 trues, 50 falses, 50 non-existents
res0: all objects                      (150 found, 150 scanned)
res1: deleted is false                 (50 found, 50 scanned)
res2: deleted is true                  (50 found, 50 scanned)
res3: deleted is non-existent          (50 found, 50 scanned)
res4: deleted is false or non-existent (100 found, 100 scanned)
res5: deleted is true or non-existent  (100 found, 100 scanned)
res6: deleted is in [false,null]       (100 found, 100 scanned)

집약 파이프라인에서 필요한 경우find이것은 나에게 효과가 있었다.

db.getCollection('tests').aggregate([ 
  // ...previous operations...
  { $addFields: { "deleted_conclusion": { $cond: {
        if:{ $ne: [ "$deleted", false ]}, then: { $cond: [ "$deleted", ":TRUE", ":FALSY"]}, else: ":FALSE"
  }}}}
])

추가 필드를 추가한 후 파이프라인 단계를 진행하여 놓치는 정보를 얻을 수 있습니다.

mongoid 구문을 찾고 있는 경우(레일 앱에서 사용하고 있는 경우)는 다음과 같습니다.

2.3.1 :042 > accepted_consent = org.users.active.where(:accepted_terms_and_conditions => true).count
 => 553 
2.3.1 :043 > not_accepted_yet = org.users.active.where(:accepted_terms_and_conditions.ne => true).count
 => 6331 
2.3.1 :044 > 6331+553
 => 6884 
2.3.1 :045 > org.users.active.count
 => 6884 

언급URL : https://stackoverflow.com/questions/18837486/query-for-boolean-field-as-not-true-e-g-either-false-or-non-existent

반응형