MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Spring Data MongoDB – индекси, анотации и конвертори

1. Прегледа

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

2. Индексии

2.1. @Индексирано

Тази анотация маркира полето като индексирано в MongoDB:

@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() метод в нашия MongoConfig :

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-index-creation свойството на true .

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

Можем също да създадем индекс програмно:

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

Вече създадохме индекс за полето name и резултатът ще бъде същият като в предишния раздел.

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. @Преходно

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

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;

Сега emailAddress ще бъде запазен в базата данни с помощта на ключа email:

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 маркира конструктор, дори такъв, който е защитен с пакет, като основен конструктор, използван от логиката за постоянство. Аргументите на конструктора се съпоставят по име с ключовите стойности в извлечения DBObject .

Нека разгледаме този конструктор за нашия Потребител клас:

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

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

В нашия пример ако възраст не е зададено, ще бъде настроено на 0 по подразбиране.

Нека сега да видим как работи:

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

Нашата база данни ще изглежда:

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

И така, възраст полето е null , но когато правим заявка за документа и извличаме възраст :

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

Резултатът ще бъде 0.

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

Нека сега да разгледаме друга много полезна функция в Spring Data MongoDB – конвертори, и по-специално MongoConverter .

Това се използва за обработка на съпоставянето на всички типове Java към DBObjects при съхраняване и запитване на тези обекти.

Имаме две опции – можем да работим или с MappingMongoConverter – или SimpleMongoConverter в по-ранни версии (това беше отхвърлено в Spring Data MongoDB M3 и неговата функционалност беше преместена в MappingMongoConverter ).

Или можем да напишем наш собствен персонализиран конвертор. За да направим това, ще трябва да внедрим Конвертора интерфейс и регистрирайте реализацията в MongoConfig.

Нека разгледаме бърз пример . Както видяхме в някои от изхода на JSON тук, всички обекти, записани в база данни, имат полето _class който се записва автоматично. Ако обаче искаме да пропуснем това конкретно поле по време на постоянство, можем да направим това с помощта на MappingMongoConverter .

Първо – ето персонализираната реализация на конвертора:

@Component
public class UserWriterConverter implements Converter<User, DBObject> {
    @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<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();

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

Разбира се, можем да постигнем същия резултат и с XML конфигурация, ако трябва:

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

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

Сега, когато запазим нов потребител:

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

Полученият документ в базата данни вече не съдържа информацията за класа:

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

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Вмъкнете стойност на конкретна позиция в масив в MongoDB

  2. MongoDB група по стойности в поле на масив

  3. Причини за и против преминаването от SQL сървър към MongoDB

  4. Избягвайте предупреждението за оттегляне на текущия анализатор на URL низове, като зададете useNewUrlParser на true

  5. Как да сумирате всички полета в поддокумент на MongoDB?