예:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
$caseSensitive
은 기본적으로 이미 false이며, 색인화 된 필드에서만 작동하기 때문에 질문에 대답하지 않습니다. OP는 대소 문자를 구분하지 않는 문자열 비교를 찾고있었습니다.
예:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
$caseSensitive
은 기본적으로 이미 false이며, 색인화 된 필드에서만 작동하기 때문에 질문에 대답하지 않습니다. OP는 대소 문자를 구분하지 않는 문자열 비교를 찾고있었습니다.
답변:
정규식을 사용할 수 있습니다 .
귀하의 예에서 다음과 같습니다.
db.stuff.find( { foo: /^bar$/i } );
그래도, 당신이 찾을 때마다 추가 비용을 들이지 않고 그 길에서 가치를 소문자로 만들 수도 있습니다. 분명히 이것은 사람들의 이름과 그와 같은 경우에는 효과가 없지만 태그와 같은 유스 케이스에는 적합하지 않습니다.
최신 정보:
원래의 대답은 이제 더 이상 사용되지 않습니다. Mongodb는 이제 많은 기능을 갖춘 고급 전체 텍스트 검색을 지원합니다.
원래 답변 :
정규 표현식의 대소 문자를 구분하지 않는 / i로 검색하면 mongodb가 색인으로 검색 할 수 없으므로 큰 데이터 세트에 대한 쿼리에 시간이 오래 걸릴 수 있습니다.
작은 데이터 세트를 사용하더라도 효율성이 떨어집니다. 쿼리 영장보다 훨씬 큰 CPU 적중률을 취하면 규모를 달성하려는 경우 문제가 될 수 있습니다.
대안으로 대문자 사본을 저장하고 검색 할 수 있습니다. 예를 들어, 사용자 이름이 대소 문자가 혼합 된 User 테이블이 있지만 ID는 사용자 이름의 대문자 사본입니다. 이렇게하면 대소 문자를 구분하는 복제가 불가능합니다 ( "Foo"와 "foo"가 모두 허용되지 않음). id = username.toUpperCase ()로 검색하여 대소 문자를 구분하지 않는 사용자 이름을 검색 할 수 있습니다.
메시지 본문과 같이 필드가 큰 경우 데이터 복제는 좋은 옵션이 아닙니다. 필자는 Apache Lucene과 같은 외부 인덱서를 사용하는 것이 가장 좋은 방법이라고 생각합니다.
username: 'bill'
일치 BILL
또는 Bill
도 일치하는 것이다 전체 텍스트 검색 쿼리가 아닌 단어 형태소 의이 bill
같은 Bills
, billed
등
변수에서 정규 표현식을 만들어야하는 경우이 방법을 사용하는 것이 더 좋습니다. https://stackoverflow.com/a/10728069/309514
그런 다음 다음과 같은 작업을 수행 할 수 있습니다.
var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );
이것은 프로그래밍 방식이 향상되는 이점이 있거나 많이 재사용하는 경우 미리 컴파일하여 성능을 향상시킬 수 있습니다.
new RegExp("^" + req.params.term.toLowerCase(), "i")
또한 잘 작동
이전 예는 다음과 같습니다.
db.stuff.find( { foo: /bar/i } );
bar 를 포함하는 모든 항목 이 쿼리 (bar1, barxyz, openbar)와 일치하게하면 인증 함수에서 사용자 이름을 검색하는 것이 매우 위험 할 수 있습니다 ...
적절한 정규 표현식 구문을 사용하여 검색어와 만 일치시켜야 할 수도 있습니다.
db.stuff.find( { foo: /^bar$/i } );
정규식에 대한 구문 도움말 은 http://www.regular-expressions.info/ 를 참조하십시오 .
MongoDB 3.4부터는 대소 문자를 구분하지 않고 빠른 검색을 수행하기 위해 권장되는 방법은 대소 문자 구분 색인 을 사용하는 것 입니다.
나는 개인적으로 설립자 중 한 명에게 이메일을 보내이 작업을 수행하도록 도와주었습니다. 2009 년 이후 JIRA 에서 문제 였으며 많은 사람들이이 기능을 요청했습니다. 작동 방식은 다음과 같습니다.
대소 문자를 구분하지 않는 색인은 1 또는 2의 강도로 데이터 정렬 을 지정하여 작성됩니다. 다음과 같이 대소 문자를 구분하지 않는 색인을 작성할 수 있습니다.
db.cities.createIndex(
{ city: 1 },
{
collation: {
locale: 'en',
strength: 2
}
}
);
컬렉션을 만들 때 컬렉션 당 기본 데이터 정렬을 지정할 수도 있습니다.
db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
두 경우 모두 대소 문자를 구분하지 않는 색인 find
을 사용하려면 색인 또는 콜렉션을 작성할 때 사용 된 조작 에서 동일한 데이터 정렬을 지정해야합니다 .
db.cities.find(
{ city: 'new york' }
).collation(
{ locale: 'en', strength: 2 }
);
"New York", "New York", "New York"등을 반환합니다.
username: 'bill'
일치 BILL
또는 Bill
도 일치하는 것이 아니라 전체 텍스트 검색 쿼리, 막아야 의 말 bill
등, Bills
, billed
등색인을 사용하더라도 문서에 다음 과 같이 명시 되어 있기 때문에 정규 표현식 사용을 제안하는 답변이 느립니다 .
"대소 문자를 구분하지 않는 정규 표현식 쿼리는 일반적으로 인덱스를 효과적으로 사용할 수 없습니다. $ regex 구현은 데이터 정렬을 인식하지 않으며 대소 문자를 구분하지 않는 인덱스를 사용할 수 없습니다."
$regex
응답은 또한 사용자 입력 주입 의 위험을 초래 합니다.
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity
TL; DR
RegExp를 사용하지 마십시오
db.articles.insert(
[
{ _id: 1, subject: "coffee", author: "xyz", views: 50 },
{ _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
{ _id: 3, subject: "Baking a cake", author: "abc", views: 90 },
{ _id: 4, subject: "baking", author: "xyz", views: 100 },
{ _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
{ _id: 6, subject: "Сырники", author: "jkl", views: 80 },
{ _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
{ _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
]
)
쿼리를 인덱싱하지 않고 검색하려는 TEXT 필드 에 인덱스를 생성해야합니다.
db.articles.createIndex( { subject: "text" } )
db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } ) //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
username: 'bill'
일치 BILL
또는 Bill
도 일치하는 것이다 전체 텍스트 검색 쿼리가 아닌 단어 형태소 의이 bill
같은 Bills
, billed
등
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
$existing = Users::masterFind('all', ['conditions' => ['traits.0.email' => ['$regex' => "^$value$", '$options' => 'i']]]);
Mongo (현재 버전 2.0.0)에서는 인덱싱 된 필드에 대해 대소 문자를 구분하지 않는 검색을 허용하지 않습니다 ( 문서 참조) . 색인이 생성되지 않은 필드의 경우 다른 답변에 나열된 정규 표현식이 좋습니다.
Regex 기반 쿼리를 사용할 때 명심해야 할 한 가지 중요한 사항-로그인 시스템에서이 작업을 수행 할 때 검색중인 모든 단일 문자 를 이스케이프 하고 ^ 및 $ 연산자를 잊지 마십시오. Lodash는 이미 사용하고 있다면 이것을 위해 좋은 기능을 가지고 있습니다.
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
왜? 사용자 .*
가 자신의 사용자 이름으로 입력한다고 상상해보십시오 . 모든 사용자 이름과 일치하므로 사용자의 비밀번호를 추측하여 로그인 할 수 있습니다.
가장 좋은 방법은 선택한 언어로, 객체에 대한 모델 래퍼를 만들 때 검색 할 필드 집합을 통해 save () 메서드가 반복되도록합니다. 이러한 필드 세트에는 소문자 대응 물이 있어야하며 검색에 사용됩니다.
객체가 다시 저장 될 때마다 소문자 속성이 확인되고 기본 속성이 변경되면 업데이트됩니다. 이렇게하면 효율적으로 검색 할 수 있지만 매번 lc 필드를 업데이트하는 데 필요한 추가 작업을 숨길 수 있습니다.
소문자 필드는 key : value 객체 저장소이거나 접두사가 lc_ 인 필드 이름 일 수 있습니다. 두 번째 쿼리를 사용하여 쿼리를 단순화합니다 (심층 객체 쿼리는 때때로 혼동 될 수 있음).
참고 : 기본 필드가 아닌 lc_ 필드를 색인화하려고합니다.
"표"에서 "열"을 검색하고 대소 문자를 구분하지 않는 검색을 원한다고 가정합니다. 가장 효율적인 방법은 다음과 같습니다.
//create empty JSON Object
mycolumn = {};
//check if column has valid value
if(column) {
mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);
위의 코드는 검색 값을 RegEx로 추가하고 옵션으로 "i"를 사용하여 감지되지 않은 기준으로 검색합니다.
모두 제일 좋다.
Mongoose를 사용하면 이것이 나를 위해 일했습니다.
var find = function(username, next){
User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
if(err) throw err;
next(null, res);
});
}
.toLowerCase()
대소 문자를 구분하지 않는 플래그를 지정하는 경우 중복 되지 i
않습니까?
집계 프레임 워크는 mongodb 2.2에서 도입되었습니다. 문자열 연산자 "$ strcasecmp"를 사용하여 대소 문자를 구분하지 않고 문자열을 비교할 수 있습니다. 정규식을 사용하는 것보다 더 권장되고 쉽습니다.
집계 명령 연산자 ( https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp) 에 대한 공식 문서는 다음과 같습니다 .
대소 문자를 구분하지 않는 인덱스를 사용할 수 있습니다 .
다음 예제에서는 기본 데이터 정렬이없는 컬렉션을 만든 다음 대 / 소문자를 구분하지 않는 데이터 정렬을 사용하여 이름 필드에 인덱스를 추가합니다. 유니 코드 용 국제 구성 요소
/* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )
인덱스를 사용하려면 쿼리에서 동일한 데이터 정렬을 지정해야합니다.
db.users.insert( [ { name: "Oğuz" },
{ name: "oğuz" },
{ name: "OĞUZ" } ] )
// does not use index, finds one result
db.users.find( { name: "oğuz" } )
// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )
// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )
또는 기본 데이터 정렬을 사용하여 컬렉션을 만들 수 있습니다.
db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation
db.users.createIndex( { name: 1 }, {collation: { locale: 'tr', strength: 2 } } )
변수를 검색하고 탈출하려면 :
const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})
변수를 이스케이프하면 '. *'또는 다른 정규식을 사용한 공격으로부터 쿼리를 보호합니다.
RegExp를 사용하십시오. 다른 옵션이 작동하지 않으면 RegExp가 좋은 옵션입니다. 문자열 대소 문자를 구분하지 않습니다.
var username = new RegExp("^" + "John" + "$", "i");;
쿼리에 사용자 이름을 사용한 다음 완료하십시오.
나는 그것이 당신에게도 효과가 있기를 바랍니다. 모두 제일 좋다.
필터에 사용하는 대소 문자를 구분하지 않는 정규 표현식에 대한 간단한 Func를 만들었습니다.
private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) =>
BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));
그런 다음 단순히 다음과 같이 필드를 필터링합니다.
db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();
C #에서 필터를 사용하면 효과적입니다.
string s = "searchTerm";
var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
var listSorted = collection.Find(filter).ToList();
var list = collection.Find(filter).ToList();
반환이 발생한 후 메소드가 호출된다고 생각하기 때문에 인덱스를 사용할 수도 있지만 아직 테스트하지 않았습니다.
이것은 또한 문제를 피합니다
var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());
그 mongodb는 p.Title.ToLower ()가 속성이며 올바르게 매핑되지 않는다고 생각합니다.
Golang을 사용하고 mongodb 및 mgo godoc globalsign 라이브러리를 사용하여 대소 문자를 구분하여 전체 텍스트를 검색하려는 경우 .
collation := &mgo.Collation{
Locale: "en",
Strength: 2,
}
err := collection.Find(query).Collation(collation)
mongo docs에서 볼 수 있듯이 버전 3.2 $text
인덱스는 기본적으로 대소 문자를 구분하지 않으므로 https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity
username: 'bill'
일치 BILL
또는 Bill
도 일치하는 것이다 전체 텍스트 검색 쿼리가 아닌 단어 형태소 의이 bill
같은 Bills
, billed
등
이것들은 문자열 검색을 위해 테스트되었습니다
{'_id': /.*CM.*/} ||find _id where _id contains ->CM
{'_id': /^CM/} ||find _id where _id starts ->CM
{'_id': /CM$/} ||find _id where _id ends ->CM
{'_id': /.*UcM075237.*/i} ||find _id where _id contains ->UcM075237, ignore upper/lower case
{'_id': /^UcM075237/i} ||find _id where _id starts ->UcM075237, ignore upper/lower case
{'_id': /UcM075237$/i} ||find _id where _id ends ->UcM075237, ignore upper/lower case
나는 비슷한 문제에 직면했으며 이것이 나를 위해 일한 것입니다.
const flavorExists = await Flavors.findOne({
'flavor.name': { $regex: flavorName, $options: 'i' },
});
$regex
편집에서 설명했듯이 사용 은 비효율적이며 잠재적으로 안전하지 않습니다. 커뮤니티에 더 이상 서비스를 제공하지 않으면 답변을 삭제해도 수치가 없습니다!
$caseSensitive: false
. 참조 : docs.mongodb.org/manual/reference/operator/query/text/…