programing

mongoDB의 문자열 필드 값 길이

madecode 2023. 2. 22. 23:25
반응형

mongoDB의 문자열 필드 값 길이

필드의 데이터 유형은 String입니다.필드 이름의 문자 길이가 40자 이상인 데이터를 가져오고 싶습니다.

이 쿼리를 시도했지만 오류가 반환되었습니다.1 .

db.usercollection.find(
{$where: "(this.name.length > 40)"}
).limit(2);

output :error: {
    "$err" : "TypeError: Cannot read property 'length' of undefined near '40)' ",
    "code" : 16722
}

이것은 2.4.9에서 동작하고 있습니다만, 제 버전은 2.6.5입니다.

MongoDB 3.6 이후의 경우:

연산자는 쿼리 언어 내에서 집약식을 사용할 수 있으므로 연산자를 사용하여 다음과 같이 문자열 길이를 확인할 수 있습니다.

db.usercollection.find({ 
    name: { $exists: true },
    $expr: { $gt: [{ $strLenCP: '$name' }, 40] } 
})

MongoDB 3.4 이후의 경우:

또한 파이프라인 연산자와 함께 집계 프레임워크를 사용하여 논리 조건을 처리하고 특수 작업을 사용하여 논리 조건이 참인 문서를 "보관"하거나 조건이 거짓인 문서를 "제거"할 수 있습니다.

이 작업은 컬렉션에서 필드를 선택하고 논리 조건 쿼리의 결과를 보관하는 새 필드를 생성하는 파이프라인과 유사하지만 이 작업에서는 보다 효율적인 단일 파이프라인 단계를 사용합니다.

논리 조건에 대해서는 연산자를 사용하여 문자열 길이를 확인할 수 있는 String Aggregation 연산자가 있습니다.길이가 지정된 값인 경우, 이는 진정한 일치이며 문서는 "kept"입니다.그렇지 않으면 "자른" 상태로 폐기됩니다.


상기의 개념을 나타내는 다음의 집약 조작을 실행하는 것을 검토해 주십시오.

db.usercollection.aggregate([
    { $match: { name: { $exists: true } } },
    { $redact: {
         $cond: [
            { $gt: [ { $strLenCP: "$name" }, 40] },
            "$$KEEP",
            "$$PRUNE"
        ]
    } },
    { $limit: 2 }
])

를 사용하는 경우 괄호 없이 쿼리를 시도합니다.

db.usercollection.find({ $where: "this.name.length > 40" }).limit(2);

더 나은 쿼리는 필드의 존재를 확인한 다음 길이를 확인하는 것입니다.

db.usercollection.find({ name: { $type: 2 }, $where: "this.name.length > 40" }).limit(2); 

또는 다음과 같이 입력합니다.

db.usercollection.find({ name: { $exists: true }, $where: "this.name.length > 
40" }).limit(2); 

MongoDB는 식과 비식 전에 비쿼리 연산을 평가합니다$where.$where질의문은 색인을 사용할 수 있습니다.보다 뛰어난 퍼포먼스는 문자열의 길이를 다른 필드로 저장한 후 인덱싱 또는 검색할 수 있습니다.이것에 비해 적용에 시간이 걸립니다.다른 방법으로 데이터를 구조화할 수 없거나 데이터의 작은 서브셋을 처리할 때 마지막 수단으로 JavaScript 식과 연산자를 사용하는 것이 좋습니다.


오퍼레이터의 사용을 회피하는 다른 고속 접근방식은 오퍼레이터입니다.다음 패턴을 고려하여 다음 패턴을 검색합니다.

db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2); 

참고 - 문서에서:

필드에 인덱스가 존재하는 경우 MongoDB는 인덱스의 값과 정규식을 대조합니다.이 값은 수집 스캔보다 빠를 수 있습니다.정규 표현이 "prefix expression"인 경우 추가 최적화가 발생할 수 있습니다. 즉, 모든 일치 가능성이 동일한 문자열로 시작됩니다.이것에 의해, MongoDB 는 그 프리픽스에서 「범위」를 작성해, 그 범위에 포함되는 인덱스의 값에 대해서만 일치시킬 수 있습니다.

은 캐럿으로 식입니다.(^) "" " " " " " "(\A) 나옵니다.들어 regex 입니다./^abc.*/값 중 "로 시작하는 됩니다.abc.

★에서는,/^a/, /^a.*/, ★★★★★★★★★★★★★★★★★」/^a.*$/일치하는 문자열은 서로 다른 성능 특성을 가집니다.은 모두 존재하는 「인덱스」는, 「인덱스」를 사용합니다./^a.*/ , , , , 입니다./^a.*$/더 느리다. /^a/는 프리픽스를 일치시킨 후에 스캔을 정지할 수 있습니다.

「」를 사용한 $where ★★★★★★★★★★★★★★★★★」$expr문서가 너무 많으면 느려집니다.

「」를 사용합니다.$regex가 훨씬 빠르다$where,$expr.

db.usercollection.find({ 
  "name": /^[\s\S]{40,}$/, // name.length >= 40
})

or 

db.usercollection.find({ 
  "name": { "$regex": "^[\s\S]{40,}$" }, // name.length >= 40
})

이 쿼리는 다음과 같은 의미입니다.

db.usercollection.find({ 
  "$where": "this.name && this.name.length >= 40",
})

or

db.usercollection.find({ 
    "name": { "$exists": true },
    "$expr": { "$gte": [ { "$strLenCP": "$name" }, 40 ] } 
})

나는 내 수집품에 대해 각 쿼리를 테스트했다.

# find
$where: 10529.359ms
$expr: 5305.801ms
$regex: 2516.124ms

# count
$where: 10872.006ms
$expr: 2630.155ms
$regex: 158.066ms

여기 mongodb에서 이것을 달성할 수 있는 방법 중 하나가 있다.

db.usercollection.find({ $where: 'this.name.length < 4' })

이 쿼리는 필드 값과 길이를 모두 제공합니다.

db.usercollection.aggregate([
{
    $project: {
        "name": 1,
        "length": { $strLenCP: "$name" }
    }} ])

저도 비슷한 시나리오였지만, 제 경우 문자열은 1레벨 속성이 아닙니다.그것은 물건 안에 있다.여기서는 그것에 대한 적절한 답을 찾을 수 없었다.그래서 저는 저의 해결책을 여러분들과 공유하고 싶었습니다(이것이 비슷한 종류의 문제를 가진 모든 사람에게 도움이 되기를 바랍니다).

Parent Collection 

{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}

예: 아이의 이름 길이가 10글자 이상일 경우에만 수집해야 하는 경우

 db.getCollection('Parent').find({$where: function() { 
for (var field in this.Child.name) { 
    if (this.Child.name.length > 10) 
        return true;

}
}})

「 」로 .name 40자 이상:

db.usercollection.find({name: /.{40}/})

(카라사와 후미야의 답변에서 RegEx를 간략화)

언급URL : https://stackoverflow.com/questions/29577713/string-field-value-length-in-mongodb

반응형