2012-10-04 24 views
11

मैं दो डोमेन ऑब्जेक्ट के लिए findBy विधि,वसंत डेटा - MongoDB - नेस्टेड वस्तुओं

@Document 
public class PracticeQuestion { 

    private int userId; 
    private List<Question> questions; 

// Getters and setters 
} 

@Document 
public class Question { 

    private int questionID; 
    private String type; 

// Getters and setters 
} 

मेरे JSON दस्तावेज़ इस तरह है,

{ 
    "_id" : ObjectId("506d9c0ce4b005cb478c2e97"), 
    "userId" : 1, 
    "questions" : [ 
     { 
      "questionID" : 1, 
      "type" : "optional" 

     }, 
     { 
      "questionID" : 3, 
      "type" : "mandatory" 
     } 
    ] 
} 

मैं "प्रकार" के आधार पर अपडेट करना पड़ता है userId और questionId, तो मैं कस्टम भंडार इंटरफेस के अंदर एक findBy क्वेरी विधि लिखा है,

public interface CustomRepository extends MongoRepository<PracticeQuestion, String> { 

    List<PracticeQuestion> findByUserIdAndQuestionsQuestionID(int userId,int questionID);  
} 

मेरे समस्या है जब मैं इस विधि को userId के साथ 1 और प्रश्न 3 के रूप में निष्पादित करता हूं, तो यह प्रश्न आईडी के बावजूद पूरी प्रश्न सूची देता है। क्या क्वेरी विधि का नाम मान्य है या मुझे नेस्टेड ऑब्जेक्ट्स के लिए क्वेरी कैसे लिखनी चाहिए।

किसी भी सुझाव के लिए धन्यवाद।

उत्तर

14

बस उस विधि पर @Query एनोटेशन का उपयोग करें।

public interface CustomRepository extends MongoRepository<PracticeQuestion, String> { 

    @Query(value = "{ 'userId' : ?0, 'questions.questionID' : ?1 }", fields = "{ 'questions.questionID' : 1 }") 
    List<PracticeQuestion> findByUserIdAndQuestionsQuestionID(int userId, int questionID); 

} 

@Query एनोटेशन के fields हिस्सा जोड़कर, आप मोंगो कह रहे हैं केवल दस्तावेज़ का वह हिस्सा वापस जाने के लिए। सावधान रहें, फिर भी यह पूरे दस्तावेज़ को उसी प्रारूप में वापस कर देता है - बस जो कुछ भी आपने निर्दिष्ट नहीं किया है उसे याद कर रहा है। तो अपने कोड अभी भी List<PracticeQuestion> वापस जाने के लिए है और आप क्या करना होगा:

foreach (PracticeQuestion pq : practiceQuestions) { 
    Question q = pq.getQuestions().get(0); // This should be your question. 
} 
+0

धन्यवाद, लेकिन फिर इस प्रश्न के एक रिटर्न सरणी में उचित तत्व के बजाय सरणी। – user1720083

+1

ओह। मुझे पता है तुम्हारा क्या मतलब है। आप केवल पूरे दस्तावेज़ को वापस कर सकते हैं। क्वेरी वास्तव में ऐसे दस्तावेजों की तलाश करती है जिनके पास प्रश्न आईडी है। लेकिन आप हमेशा पूरा दस्तावेज़ लौटाते हैं - कभी सवाल नहीं। यह एक जावा चीज नहीं है, यह एक मोंगोडीबी चीज है।स्पष्टीकरण के लिए इस प्रश्न/उत्तर को देखें: http://stackoverflow.com/a/3985982/229178 – sbzoom

+1

कुछ होमवर्क के बाद मुझे एहसास हुआ कि आप अपनी क्वेरी ('अनुमान 'के' फ़ील्ड 'भाग में आंशिक वस्तुओं को निर्दिष्ट कर सकते हैं। http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+ फ़ील्ड मैं उदाहरण देने के लिए उपरोक्त मेरा उत्तर अपडेट करूंगा। – sbzoom

5

संपत्ति अभिव्यक्ति के रूप में पूर्ववर्ती उदाहरण में दिखाया गया

संपत्ति भाव, केवल प्रबंधित इकाई का एक सीधा संपत्ति का उल्लेख कर सकते। क्वेरी निर्माण समय पर आप पहले से ही सुनिश्चित कर लें कि पार्स की गई संपत्ति प्रबंधित डोमेन क्लास की एक संपत्ति है। हालांकि, आप नेस्टेड गुणों को घुमाकर बाधाओं को भी परिभाषित कर सकते हैं। मान लें कि व्यक्तियों के पास ज़िप कोड के साथ पते हैं। उस स्थिति में

की एक विधि का नाम खोजें ByAddressZipCode (ZipCode ज़िप कोड); संपत्ति ट्रैवर्सल x.address.zipCode बनाता है। रिज़ॉल्यूशन एल्गोरिदम पूरे भाग (पताZipCode) को संपत्ति के रूप में व्याख्या करने के साथ शुरू होता है और उस नाम के साथ किसी संपत्ति के लिए डोमेन क्लास की जांच करता है (अनपेक्षित)। अगर एल्गोरिदम सफल होता है तो वह उस संपत्ति का उपयोग करता है। यदि नहीं, तो एल्गोरिदम ऊंट के मामले के हिस्सों में सीधे सिर से एक सिर और पूंछ में स्रोत को विभाजित करता है और हमारे उदाहरण, पताZip और कोड में इसी संपत्ति को खोजने का प्रयास करता है। अगर एल्गोरिदम को उस सिर के साथ एक संपत्ति मिलती है तो यह पूंछ लेती है और वहां से पेड़ का निर्माण जारी रखती है, पूंछ को बस वर्णित तरीके से विभाजित करती है। यदि पहला विभाजन मेल नहीं खाता है, तो एल्गोरिदम विभाजित बिंदु को बाएं (पता, ज़िपकोड) पर ले जाता है और जारी रहता है।

हालांकि यह ज्यादातर मामलों के लिए काम करना चाहिए, एल्गोरिदम के लिए गलत संपत्ति का चयन करना संभव है। मान लीजिए कि पर्सन क्लास में एड्रेसजिप संपत्ति भी है। एल्गोरिदम पहले विभाजन में पहले से ही मिलान करेगा और अनिवार्य रूप से गलत संपत्ति का चयन करेगा और अंततः विफल हो जाएगा (क्योंकि पता ज़िप के प्रकार में शायद कोई कोड प्रॉपर्टी नहीं है)। इस अस्पष्टता को हल करने के लिए आप ट्रैवलल पॉइंट मैन्युअल रूप से परिभाषित करने के लिए अपने विधि नाम के अंदर _ का उपयोग कर सकते हैं।इसलिए हमारे विधि नाम तो जैसे खत्म होगा:

UserDataRepository:

सूची findByAddress_ZipCode (ज़िपकोड ज़िपकोड);

उपयोगकर्ता डेटा खोज ByUserId (स्ट्रिंग उपयोगकर्ता आईडी);

ProfileRepository:

प्रोफ़ाइल findByProfileId (स्ट्रिंग profileId);

UserDataRepositoryImpl:

UserData UserData = userDateRepository.findByUserId (userId);

प्रोफ़ाइल प्रोफ़ाइल = profileRepository.findByProfileId (userData.getProfileId());

userData.setProfile (प्रोफाइल);

नमूना Pojo:

सार्वजनिक वर्ग UserData {

private String userId; 
private String status; 
private Address address; 
private String profileId; 

//New Property 
private Profile profile; 

//TODO:setter & getter 

}

सार्वजनिक वर्ग प्रोफ़ाइल {

private String email; 
private String profileId; 

}

उपरोक्त दस्तावेज़/पीओजेओ के लिए आपके रिपोजिटरी क्लास में:

उपयोगकर्ताडेटा ढूँढें ByProfile_Email (स्ट्रिंग ईमेल);

रेफरी के लिए:

1) मोंगो भंडार के लिए कस्टम विधि बनाएं:: Add custom method to Repository

UnwindOperation unwind = Aggregation.unwind("questions"); 
MatchOperation match = Aggregation.match(Criteria.where("userId").is(userId).and("questions.questionId").is(questionID)); 
Aggregation aggregation = Aggregation.newAggregation(unwind,match); 
AggregationResults<PracticeQuestionUnwind> results = mongoOperations.aggregate(aggregation, "PracticeQuestion", 
       PracticeQuestionUnwind.class); 
return results.getMappedResults(); 

2) आप एक वर्ग cretae की जरूरत http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

0

आप मोंगो एकत्रीकरण ढांचे का उपयोग करने की आवश्यकता है (क्योंकि अवांछित ऑपरेशन ने वर्ग संरचना को बदल दिया है) नीचे:

public class PracticeQuestionUnwind { 
    private String userId; 
    private Question questions; 
और questionId: 111:

यह आप केवल उन जिसके परिणामस्वरूप प्रदान userId के लिए userId और questionId

परिणाम से मेल खाता है दे देंगे आप के लिए उत्तर

{ 
    "userId": "1", 
    "questions": { 
       "questionId": "111", 
       "type": "optional" 
      } 
} 
संबंधित मुद्दे