Рубрики
Без рубрики

Весенние данные MongoDB – Индексы, Аннотации и преобразователи

Как работать с индексами, преобразователи и общие аннотации в весенних данных MongoDB.

Автор оригинала: baeldung.

Весенние данные MongoDB – Индексы, Аннотации и преобразователи

1. Обзор

В этом учебнике мы изумим некоторые основные особенности Spring Data MongoDB – индексирование, общие аннотации и преобразователи.

2. Индексы

2.1. @Indexed

Это аннотация отмечает поле как индексированную в МонгоДБ:

@QueryEntity
@Document
public class User {
    @Indexed
    private String name;
    
    ... 
}

Теперь, когда имя поле индексировано – давайте посмотрим на индексы в оболочке MongoDB:

db.user.getIndexes();

Вот что мы получаем:

[
    {
        "v" : 1,
        "key" : {
             "_id" : 1
         },
        "name" : "_id_",
        "ns" : "test.user"
    }
]

Мы можем быть удивлены, что нет никаких признаков имя поле в любом месте!

Это потому, что, по данным Spring Data MongoDB 3.0 автоматическое создание индекса отключено по умолчанию .

Однако мы можем изменить это поведение, явно переопределив autoIndexCreation() метод в нашем МонгоКонфиг :

public class MongoConfig extends AbstractMongoClientConfiguration {

    // rest of the config goes here

    @Override
    protected boolean autoIndexCreation() {
        return true;
    }
}

Давайте еще раз проверим индексы в оболочке MongoDB:

[
    {
        "v" : 1,
        "key" : {
             "_id" : 1
         },
        "name" : "_id_",
        "ns" : "test.user"
    },
    {
         "v" : 1,
         "key" : {
             "name" : 1
          },
          "name" : "name",
          "ns" : "test.user"
     }
]

Как видим, на этот раз у нас два индекса – один из них _id – который был создан по умолчанию из-за @Id аннотация и второй – наш имя поле.

Кроме того, если мы используем Spring Boot, мы могли бы установить spring.data.mongodb.auto-индекс- имущество для истинное .

2.2. Создание индекса программным путем

Мы также можем создать индекс программно:

mongoOps.indexOps(User.class).
  ensureIndex(new Index().on("name", Direction.ASC));

Сейчас мы создали индекс для полевых имя и результат будет таким же, как и в предыдущем разделе.

2.3. Составные индексы

MongoDB поддерживает сложные индексы, где единая структура индекса содержит ссылки на несколько полей.

Рассмотрим быстрый пример с использованием сложных индексов:

@QueryEntity
@Document
@CompoundIndexes({
    @CompoundIndex(name = "email_age", def = "{'email.id' : 1, 'age': 1}")
})
public class User {
    //
}

Мы создали сложный индекс с электронной и возрастные Поля. Давайте теперь проверить фактические индексы:

{
    "v" : 1,
    "key" : {
        "email.id" : 1,
        "age" : 1
    },
    "name" : "email_age",
    "ns" : "test.user"
}

Обратите внимание, что DBRef поле не может быть помечено @Index – это поле может быть только частью составного индекса.

3. Общие аннотации

3.1. @Transient

Как и следовало ожидать, эта простая аннотация исключает, что поле сохраняется в базе данных:

public class User {
    
    @Transient
    private Integer yearOfBirth;
    // standard getter and setter

}

Давайте вставить пользователя с настройкой поля yearOfBirth :

User user = new User();
user.setName("Alex");
user.setYearOfBirth(1985);
mongoTemplate.insert(user);

Теперь, если мы посмотрим состояние базы данных, мы увидим, что yearOfBirth не был спасен:

{
    "_id" : ObjectId("55d8b30f758fd3c9f374499b"),
    "name" : "Alex",
    "age" : null
}

Так что если мы запросим и проверим:

mongoTemplate.findOne(Query.query(Criteria.where("name").is("Alex")), User.class).getYearOfBirth()

Результат будет нулевой .

3.2. @Field

@Field указывает ключ, используемый для поля в документе JSON:

@Field("email")
private EmailAddress emailAddress;

Теперь электронная почтаАдрес будут сохранены в базе данных с помощью ключа Электронная почта:

User user = new User();
user.setName("Brendan");
EmailAddress emailAddress = new EmailAddress();
emailAddress.setValue("[email protected]");
user.setEmailAddress(emailAddress);
mongoTemplate.insert(user);

И состояние базы данных:

{
    "_id" : ObjectId("55d076d80bad441ed114419d"),
    "name" : "Brendan",
    "age" : null,
    "email" : {
        "value" : "[email protected]"
    }
}

3.3. @PersistenceConstructor и @Value

@PersistenceConstructor отмечает конструктора, даже защищенного пакета, чтобы быть основным конструктором, используемым логикой настойчивости. Аргументы конструктора отображаются по имени на ключевые значения в извлеченной DBОбъект .

Давайте посмотрим на этого конструктора для нашего Пользователь класс:

@PersistenceConstructor
public User(String name, @Value("#root.age ?: 0") Integer age, EmailAddress emailAddress) {
    this.name =  name;
    this.age = age;
    this.emailAddress =  emailAddress;
}

Обратите внимание на использование стандартного весеннего @Value аннотация здесь. С помощью этой аннотации мы можем использовать выражения весны для преобразования значения ключа, извлеченного из базы данных, прежде чем он будет использован для построения доменного объекта. Это очень мощная и очень полезная функция здесь.

В нашем примере, если возрастные не установлен, он будет установлен на 0 по умолчанию.

Давайте теперь посмотрим, как это работает:

User user = new User();
user.setName("Alex");
mongoTemplate.insert(user);

Наша база данных будет выглядеть:

{
    "_id" : ObjectId("55d074ca0bad45f744a71318"),
    "name" : "Alex",
    "age" : null
}

Итак, возрастные поле нулевой , но когда мы запросить документ и получить возрастные :

mongoTemplate.findOne(Query.query(Criteria.where("name").is("Alex")), User.class).getAge();

Результат будет 0.

4. Преобразователи

Давайте теперь посмотрим на другую очень полезную функцию в Весенние данные MongoDB – преобразователи, и в частности на МонгоКонвертер .

Это используется для обработки отображения всех типов Java для DBОбъекты при хранении и запросе этих объектов.

У нас есть два варианта – мы можем работать с КартаМонгоКонвертер – или ПростойМонгоКонвертер в более ранних версиях (это было deprecated в весенних данных MongoDB M3 и его функциональность была перенесена в КартаМонгоКонвертер ) .

Или мы можем написать наш собственный пользовательский преобразователь. Для этого нам необходимо будет осуществить эту Конвертер интерфейс и зарегистрировать реализацию в МонгоКонфиг.

Давайте посмотрим на быстрый пример . Как мы видели на некоторых выводах JSON, все объекты, сохраненные в базе данных, имеют поле _class который сохраняется автоматически. Если, однако, мы хотели бы пропустить это конкретное поле во время настойчивости, мы можем сделать это с помощью КартаМонгоКонвертер .

Во-первых – вот пользовательские реализации преобразователь:

@Component
public class UserWriterConverter implements Converter {
    @Override
    public DBObject convert(User user) {
        DBObject dbObject = new BasicDBObject();
        dbObject.put("name", user.getName());
        dbObject.put("age", user.getAge());
        if (user.getEmailAddress() != null) {
            DBObject emailDbObject = new BasicDBObject();
            emailDbObject.put("value", user.getEmailAddress().getValue());
            dbObject.put("email", emailDbObject);
        }
        dbObject.removeField("_class");
        return dbObject;
    }
}

Обратите внимание, как мы можем легко попасть в цель не _class путем конкретного удаления поля прямо здесь.

Теперь нам нужно зарегистрировать пользовательский преобразователь:

private List> converters = new ArrayList>();

@Override
public MongoCustomConversions customConversions() {
    converters.add(new UserWriterConverter());
    return new MongoCustomConversions(converters);
}

Мы, конечно, можем достичь того же результата с конфигурацией XML, а также, если нам нужно:

<bean class="org.springframework.data.mongodb.core.MongoTemplate" id="mongoTemplate">
    <constructor-arg name="mongo" ref="mongo"></constructor-arg>
    <constructor-arg ref="mongoConverter"></constructor-arg>
    <constructor-arg name="databaseName" value="test"></constructor-arg>
</bean>

<mongo:mapping-converter base-package="org.baeldung.converter" id="mongoConverter">
    <mongo:custom-converters base-package="com.baeldung.converter"> </mongo:custom-converters>
</mongo:mapping-converter>

Теперь, когда мы спасаем нового пользователя:

User user = new User();
user.setName("Chris");
mongoOps.insert(user);

Полученный документ в базе данных больше не содержит информацию о классе:

{
    "_id" : ObjectId("55cf09790bad4394db84b853"),
    "name" : "Chris",
    "age" : null
}

5. Заключение

В этом учебнике мы рассмотрели некоторые основные концепции работы с Spring Data MongoDB – индексация, общие аннотации и преобразователи.

Реализация всех этих примеров и фрагментов кода можно найти в течение на GitHub .