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 셸에서 AggregationCollation 메서드를 사용 했습니다. 결국 우리는 이러한 쿼리를 번역하고 mongo-java-driver 라이브러리를 사용하여 간단한 Java 구현을 제공했습니다.

언제나처럼 기사의 전체 소스 코드는  GitHub에서 확인할 수 있습니다 .

Persistence footer banner