MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

स्प्रिंग डेटा MongoDB - इंडेक्स, एनोटेशन और कन्वर्टर्स

1. अवलोकन

इस ट्यूटोरियल में हम स्प्रिंग डेटा MongoDB - इंडेक्सिंग, सामान्य एनोटेशन और कन्वर्टर्स की कुछ मुख्य विशेषताओं का पता लगाएंगे।

2. अनुक्रमणिका

2.1. @अनुक्रमित

यह एनोटेशन फ़ील्ड को अनुक्रमित के रूप में चिह्नित करता है मोंगोडीबी में:

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

अब जबकि नाम फ़ील्ड अनुक्रमित है - आइए MongoDB शेल में अनुक्रमणिका पर एक नज़र डालें:

db.user.getIndexes();

यहाँ हमें क्या मिलता है:

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

हमें आश्चर्य हो सकता है कि नाम . का कोई चिन्ह नहीं है फ़ील्ड कहीं भी!

ऐसा इसलिए है, क्योंकि स्प्रिंग डेटा 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.data.mongodb.auto-index-creation सेट कर सकते हैं संपत्ति सत्य .

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 फ़ील्ड को @इंडेक्स . से चिह्नित नहीं किया जा सकता है - वह फ़ील्ड केवल एक कंपाउंड इंडेक्स का हिस्सा हो सकता है।

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. @फ़ील्ड

@फ़ील्ड 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 और @मान

@PersistenceConstructor एक कंस्ट्रक्टर को चिह्नित करता है, यहां तक ​​​​कि एक जो पैकेज संरक्षित है, दृढ़ता तर्क द्वारा उपयोग किया जाने वाला प्राथमिक कंस्ट्रक्टर होने के लिए। कंस्ट्रक्टर तर्कों को पुनः प्राप्त DBObject . में प्रमुख मानों के नाम से मैप किया जाता है ।

आइए हमारे उपयोगकर्ता . के लिए इस कंस्ट्रक्टर को देखें कक्षा:

@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 में एक और बहुत उपयोगी विशेषता पर एक नज़र डालें - कन्वर्टर्स, और विशेष रूप से MongoConverter पर। ।

इसका उपयोग सभी जावा प्रकारों के DBObjects . के मानचित्रण को संभालने के लिए किया जाता है इन वस्तुओं को संग्रहीत और क्वेरी करते समय।

हमारे पास दो विकल्प हैं - हम या तो MappingMongoConverter के साथ काम कर सकते हैं - या SimpleMongoConverter पुराने संस्करणों में (इसे स्प्रिंग डेटा 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);
}

हम निश्चित रूप से एक्सएमएल कॉन्फ़िगरेशन के साथ भी वही परिणाम प्राप्त कर सकते हैं, अगर हमें इसकी आवश्यकता है:

<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. Mongoose के साथ डेटाबेस कैसे छोड़ें?

  4. मोंगोडीबी ऑब्जेक्ट आईडी का उपयोग क्यों करता है?

  5. नेवला में नेस्टेड सरणी आबाद करें