1. 개요
기본적으로 MongoDB 엔진은 추출된 데이터를 정렬할 때 대소문자를 고려합니다. Aggregations 또는 Collations 를 지정하여 대소문자를 구분하지 않는 정렬 쿼리를 실행할 수 있습니다.
이 짧은 사용방법(예제)에서는 MongoDB Shell과 Java를 모두 사용하는 두 가지 솔루션을 살펴보겠습니다.
2. 환경 설정
우선 MongoDB 서버를 실행해야 합니다. Docker 이미지를 사용해 보겠습니다.
$ docker run -d -p 27017:27017 --name example-mongo mongo:latest
이렇게 하면 포트 27017 을 노출하는 " example- mongo " 라는 이름의 새 임시 Docker 컨테이너가 생성됩니다 . 이제 솔루션을 테스트하는 데 필요한 데이터로 기본 Mongo 데이터베이스를 생성해야 합니다.
먼저 컨테이너 내에서 Mongo Shell을 엽니다.
$ docker exec -it example-mongo mongosh
쉘에 들어가면 컨텍스트를 전환하고 " sorting "이라는 데이터베이스를 입력해 보겠습니다.
> use sorting
마지막으로 정렬 작업을 시도할 데이터를 삽입해 보겠습니다.
> db.users.insertMany([
{name: "ben", surname: "ThisField" },
{name: "aen", surname: "Does" },
{name: "Aen", surname: "Not" },
{name: "Ben", surname: "Matter" },
])
일부 문서의 이름 필드 에 유사한 값을 삽입했습니다 . 유일한 차이점은 첫 글자의 경우입니다. 이 시점에서 데이터베이스가 생성되고 데이터가 적절하게 삽입되었으므로 조치를 취할 준비가 되었습니다.
3. 기본 정렬
사용자 지정 없이 표준 쿼리를 실행해 보겠습니다.
> db.getCollection('users').find({}).sort({name:1})
반환된 데이터는 사례를 고려하여 정렬됩니다. 이것은 예를 들어 대문자 " B" 가 소문자 " a" 보다 먼저 고려됨을 의미합니다 .
[
{
_id: ..., name: 'Aen', surname: 'Not'
},
{
_id: ..., name: 'Ben', surname: 'Matter'
},
{
_id: ..., name: 'aen', surname: 'Does'
},
{
_id: ..., name: 'ben', surname: 'ThisField'
}
]
이제 Ben 과 ben 이 함께 표시 되도록 대소문자를 구분하지 않고 정렬하는 방법을 살펴보겠습니다 .
4. Mongo Shell에서 대소문자를 구분하지 않는 정렬
4.1. 데이터 정렬을 사용하여 정렬
MongoDB 데이터 정렬 을 사용해 봅시다 . MongoDB 3.4 및 후속 버전에서만 사용할 수 있으며 문자열 비교를 위한 언어별 규칙을 활성화합니다.
데이터 정렬 ICU 로케일 매개변수는 데이터베이스가 정렬하는 방법을 결정합니다. "en" (영어) 로케일 을 사용하겠습니다 .
> db.getCollection('users').find({}).collation({locale: "en"}).sort({name:1})
이렇게 하면 이름이 문자별로 클러스터링된 출력이 생성됩니다.
[
{
_id: ..., name: 'aen', surname: 'Does'
},
{
_id: ..., name: 'Aen', surname: 'Not'
},
{
_id: ..., name: 'ben', surname: 'ThisField'
},
{
_id: ..., name: 'Ben', surname: 'Matter'
}
]
4.2. 집계 를 사용하여 정렬
이제 Aggregation 함수를 사용해 보겠습니다.
> db.getCollection('users').aggregate([{
"$project": {
"name": 1,
"surname": 1,
"lowerName": {
"$toLower": "$name"
}
}
},
{
"$sort": {
"lowerName": 1
}
}
])
$project 기능을 사용하여 이름 필드 의 소문자 버전으로 lowerName 필드를 추가 합니다. 이렇게 하면 해당 필드를 사용하여 정렬할 수 있습니다. 원하는 정렬 순서로 추가 필드가 있는 결과 개체를 제공합니다.
[
{
_id: ..., name: 'aen', surname: 'Does', lowerName: 'aen'
},
{
_id: ..., name: 'Aen', surname: 'Not', lowerName: 'aen'
},
{
_id: ..., name: 'ben', surname: 'ThisField', lowerName: 'ben'
},
{
_id: ..., name: 'Ben', surname: 'Matter', lowerName: 'ben'
}
]
5. Java를 사용한 대소문자 구분 정렬
Java에서 동일한 메서드를 구현해 봅시다.
5.1. 구성 상용구 코드
먼저 mongo-java-driver 의존성을 추가해 보겠습니다.
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.10</version>
</dependency>
그런 다음 MongoClient 를 사용하여 연결해 보겠습니다 .
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("sorting");
MongoCollection<Document> collection = db.getCollection("users");
5.2. Java에서 데이터 정렬을 사용하여 정렬
Java에서 "데이터 정렬" 솔루션 을 구현하는 것이 어떻게 가능한지 살펴보겠습니다 .
FindIterable<Document> nameDoc = collection.find().sort(ascending("name"))
.collation(Collation.builder().locale("en").build());
여기서 "en" 로케일을 사용하여 데이터 정렬을 구축했습니다. 그런 다음 생성된 Collation 객체를 FindIterable 객체의 collation 메서드에 전달했습니다 .
다음으로 MongoCursor 를 사용하여 결과를 하나씩 읽어 보겠습니다 .
MongoCursor cursor = nameDoc.cursor();
List expectedNamesOrdering = Arrays.asList("aen", "Aen", "ben", "Ben", "cen", "Cen");
List actualNamesOrdering = new ArrayList<>();
while (cursor.hasNext()) {
Document document = cursor.next();
actualNamesOrdering.add(document.get("name").toString());
}
assertEquals(expectedNamesOrdering, actualNamesOrdering);
5.3. Java에서 집계를 사용하여 정렬
Aggregation 을 사용하여 컬렉션을 정렬할 수도 있습니다 . Java API를 사용하여 명령줄 버전을 다시 만들어 보겠습니다.
먼저 Bson 객체 를 생성하기 위해 프로젝트 메서드에 의존합니다. 이 개체에는 Projections 클래스 를 사용하여 이름의 모든 문자를 소문자로 변환하여 계산되는 lowerName 필드도 포함됩니다.
Bson projectBson = project(
Projections.fields(
Projections.include("name","surname"),
Projections.computed("lowerName", Projections.computed("$toLower", "$name"))));
다음으로 이전 스니펫 의 Bson 과 정렬 방법 을 포함하는 List을 집계 방법에 제공합니다.
AggregateIterable<Document> nameDoc = collection.aggregate(
Arrays.asList(projectBson,
sort(Sorts.ascending("lowerName"))));
이 경우 이전과 마찬가지로 MongoCursor 를 사용하여 결과를 쉽게 읽을 수 있습니다 .
6. 결론
이 기사에서는 MongoDB 컬렉션의 대소문자를 구분하지 않는 간단한 정렬을 수행하는 방법을 살펴보았습니다.
MongoDB 셸에서 Aggregation 및 Collation 메서드를 사용 했습니다. 결국 우리는 이러한 쿼리를 번역하고 mongo-java-driver 라이브러리를 사용하여 간단한 Java 구현을 제공했습니다.
언제나처럼 기사의 전체 소스 코드는 GitHub에서 확인할 수 있습니다 .