2010-07-26 12 views
5

मैं एक मॉडल आईपी पतों की श्रेणियों युक्त है यह करने के लिए, समान:ऐप इंजन डेटास्टोर पर समकक्ष क्वेरी के बीच?

SELECT * FROM Country WHERE ipnum BETWEEN begin_ipnum AND end_ipnum 
:

class Country(db.Model): 
    begin_ipnum = db.IntegerProperty() 
    end_ipnum = db.IntegerProperty() 

एक SQL डेटाबेस पर, मैं पंक्तियाँ जो इस तरह एक निश्चित सीमा में एक आईपी निहित खोजने के लिए सक्षम हो जाएगा

या इस:

SELECT * FROM Country WHERE begin_ipnum < ipnum AND end_ipnum > ipnum 

दुःख की बात है GQL केवल असमानता फिल्टर एक संपत्ति पर अनुमति देता है, और BETWEEN वाक्य रचना का समर्थन नहीं करता। मैं इसके आसपास कैसे काम कर सकता हूं और ऐप इंजन पर इनके बराबर एक क्वेरी कैसे बना सकता हूं?

इसके अलावा, ListProperty 'लाइव' हो सकता है या रिकॉर्ड होने पर इसे गणना की जानी चाहिए?

सवाल एक समाधान पर एक प्रथम चाकू के साथ अद्यतन:

तो इस प्रकार के नीचे डेविड के जवाब और लेख के आधार पर:

http://appengine-cookbook.appspot.com/recipe/custom-model-properties-are-cute/

मैं एक कस्टम फ़ील्ड जोड़ने के लिए कोशिश कर रहा हूँ मेरे मॉडल के लिए:

class IpRangeProperty(db.Property): 
    def __init__(self, begin=None, end=None, **kwargs): 
    if not isinstance(begin, db.IntegerProperty) or not isinstance(end, db.IntegerProperty): 
     raise TypeError('Begin and End must be Integers.') 
    self.begin = begin 
    self.end = end 
    super(IpRangeProperty, self).__init__(self.begin, self.end, **kwargs) 

    def get_value_for_datastore(self, model_instance): 
    begin = self.begin.get_value_for_datastore(model_instance) 
    end = self.end.get_value_for_datastore(model_instance) 
    if begin is not None and end is not None: 
     return range(begin, end) 

class Country(db.Model): 
    begin_ipnum = db.IntegerProperty() 
    end_ipnum = db.IntegerProperty() 
    ip_range = IpRangeProperty(begin=begin_ipnum, end=end_ipnum) 

सोच यह है कि मैं custo जोड़ने के बाद मीटर संपत्ति मैं सिर्फ मेरी डाटासेट आयात कर सकते हैं के रूप में और उसके बाद तो जैसे ListProperty के आधार पर क्वेरी चला:

q = Country.gql('WHERE ip_range = :1', my_num_ipaddress) 

जब मैं नया देश वस्तुओं हालांकि इस विफल रहता है सम्मिलित करने के लिए प्रयास करते हैं, नाम बनाने में सक्षम नहीं होने के बारे में complaning :

... 
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py", line 619, in _attr_name 
return '_' + self.name 
TypeError: cannot concatenate 'str' and 'IntegerProperty' objects 

मैं नई संपत्ति के लिए एक attr_name विधि को परिभाषित करने के लिए या सिर्फ self.name की स्थापना, लेकिन यह मदद करने के लिए प्रतीत नहीं होता है की कोशिश की। निराशाजनक ढंग से अटक या सही दिशा में शीर्षक?

उत्तर

2

संक्षिप्त उत्तर: प्रश्नों के बीच वास्तव में इस समय समर्थित नहीं हैं। हालांकि, अगर आप एक प्राथमिकता जानते हैं कि आपकी सीमा अपेक्षाकृत छोटी हो जाएगी, तो आप इसे नकली बना सकते हैं: बस प्रत्येक संख्या के साथ इकाई पर एक सूची स्टोर करें। फिर आप उन इकाइयों को प्राप्त करने के लिए एक साधारण समानता फ़िल्टर का उपयोग कर सकते हैं जिनके श्रेणियों में एक विशेष मूल्य होता है। स्पष्ट रूप से यह काम नहीं करेगा यदि आपकी सीमा बड़ी है। लेकिन यहाँ यह कैसे काम करेगा:।

class M(db.Model): 
    r = db.ListProperty(int) 

# create an instance of M which has a range from `begin` to `end` (inclusive) 
M(r=range(begin, end+1)).put() 

# query to find instances of M which contain a value `v` 
q = M.gql('WHERE r = :1', v) 

बेहतर समाधान (अंततः - अभी केवल निम्न विकास सर्वर पर काम करता है एक बग (issue 798 देखें) की वजह से सिद्धांत रूप में, आप के आसपास काम कर सकते हैं आपके द्वारा उल्लिखित सीमाएं और db.ListProperty का लाभ उठाने के लिए एक सीमा प्रश्न निष्पादित किया गया है। विचार है कि सूची में अपनी सीमा के प्रारंभ और अंत दोनों को स्टोर करें (आपके मामले में, आईपी पते का प्रतिनिधित्व करने वाले पूर्णांक)। फिर उन इकाइयों को प्राप्त करने के लिए जिनकी श्रेणियां कुछ मूल्य v (यानी, आपकी सूची में दो मानों के बीच), आप सूची में दो असमानता फ़िल्टर के साथ एक क्वेरी निष्पादित करते हैं - यह सुनिश्चित करने के लिए कि v कम से कम सूची में सबसे छोटे तत्व के रूप में बड़ा है, और यह सुनिश्चित करने के लिए कि v है कम से कम सूची में सबसे बड़ा तत्व के रूप में छोटे।

यहाँ कैसे इस तकनीक को लागू करने का एक सरल उदाहरण है:

class M(db.Model): 
    r = db.ListProperty(int) 

# create an instance of M which has a rnage from `begin` to `end` (inclusive) 
M(r=[begin, end]).put() 

# query to find instances of M which contain a value `v` 
q = M.gql('WHERE r >= :1 AND r <= :1', v) 
+1

दुर्भाग्य से dev_appserver प्रदर्शन करता है, दुर्भाग्य से: सही व्यवहार वर्तमान उत्पादन व्यवहार है। –

+0

यह एक आशाजनक समाधान, अच्छा और सरल जैसा दिखता है। दस्तावेज़ों से ऐसा लगता है कि मैं एक कस्टम मॉडल प्रॉपर्टी बना सकता हूं जो start_ipnum और end_ipnum के मानों के आधार पर सूची मूल्य 'लाइव' की रिपोर्ट करता है। लेकिन जहां तक ​​मैं कह सकता हूं कि मैं जीक्यूएल का उपयोग कर एक कस्टम प्रॉपर्टी से पूछताछ नहीं कर पाऊंगा। तो मैं ऑब्जेक्ट सृजन पर पहले श्रेणी के लिए एक गणना सूचीप्रॉपर्टी मान का प्रयास करूंगा। मैं रिपोर्ट करूंगा कि मैं कैसे किराया करता हूं! – tijs

2

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

from google.appengine.ext import db  
class Country(db.Model): 
    subnets = db.StringListProperty() 
    country_code = db.StringProperty() 

c = Country() 
c.subnets = ['1.2.3.0/24', '1.2.0.0/16', '1.3.4.0/24'] 
c.country_code = 'US' 
c.put() 

c = Country() 
c.subnets = ['2.2.3.0/24', '2.2.0.0/16', '2.3.4.0/24'] 
c.country_code = 'CA' 
c.put() 

# Search for 1.2.4.5 starting with most specific block and then expanding until found  
result = Country.all().filter('subnets =', '1.2.4.5/32').fetch(1) 
result = Country.all().filter('subnets =', '1.2.4.4/31').fetch(1) 
result = Country.all().filter('subnets =', '1.2.4.4/30').fetch(1) 
result = Country.all().filter('subnets =', '1.2.4.0/29').fetch(1) 
# ... repeat until found 
# optimize by starting with the largest routing prefix actually found in your data (probably not 32) 
+0

साफ विचार। इसके लिए अक्सर डेटास्टोर को कई राउंड-ट्रिप की आवश्यकता होती है - जो ठीक है यदि आपको स्केल करने की आवश्यकता नहीं है, या यदि इस तरह का लुकअप कम होगा। (प्रत्येक राउंड-ट्रिप की लागत कम से कम 60-80 सेमी होगी)। –

+0

मेरा समाधान गति के लिए आपके समाधान बनाम भंडारण व्यापार करता है। मान लें कि हम सभी पते के लिए खाते हैं, आपके पास लगभग 3 बी सूची आइटम होंगे। मेरा राउंड ट्रिप कम करने के लिए आप एक ही समय में सभी संभावनाओं के लिए एक आईएन क्वेरी कर सकते हैं। – cope360

+0

एक आईएन क्वेरी निश्चित रूप से रन टाइम पर कटौती करने में मदद करेगी - हालांकि यह एक बहुत ही महंगी क्वेरी के लिए तैयार होगी क्योंकि IN क्वेरी को 30 उप-प्रश्नों में विभाजित किया जाएगा। (और यदि आप इस तरह के एक मैच चाहते थे तो लौटाए गए परिणामों पर एक मेमोरी सबसे लंबे समय तक उपसर्ग मैच; मेरे समाधान के साथ ही।) ने कहा, हालांकि महंगा पता है कि बड़ी पता श्रेणियों पर निष्पादित करना संभव है :)। (+1) –

0

यह अजीब है क्योंकि मैं एक ही मूल आधार यह पता लगाने की (130K रिकार्ड संख्या के आधार पर, आप मैक्समाइंड भू देश फ़ाइल का उपयोग कर रहे मान लेते हैं और) कोशिश कर रहा हूँ और समस्याओं के सभी प्रकार में चल रहे है। हालांकि डेविड का जवाब काफी आसान काम करेगा, यह अभ्यास में काम नहीं करता है। यह Google से:

सबसे पहले, यदि किसी प्रश्न में किसी दिए गए प्रॉपर्टी पर एकाधिक असमानता फ़िल्टर होते हैं, तो एक इकाई केवल क्वेरी से मेल खाती है यदि उसके पास उस संपत्ति के लिए एक व्यक्तिगत मान है जो सभी असमानता फ़िल्टरों से मेल खाता है। उदाहरण के लिए, यदि किसी इकाई में गुण x के लिए मान [1, 2] हैं, तो यह क्वेरी से मेल नहीं करेगा WHERE x> 1 और x < 2. प्रत्येक फ़िल्टर x के मानों में से एक से मेल खाता है, लेकिन कोई भी मान नहीं है जो दोनों से मेल खाता है फिल्टर।

मैंने बैच ने संपूर्ण डेटा सेट को सूचीप्रोपर्टी फ़ील्ड बनाने का कोई फायदा नहीं उठाया।

तो किसी भी अतिरिक्त सहायता की सराहना की जाएगी!

+0

जैसा कि आप शायद मेरे अपडेट किए गए प्रश्न से बता सकते हैं कि मैं इसे काम करने के लिए नहीं मिल सका। मैंने कुछ अन्य तरीकों की भी कोशिश की लेकिन जल्द ही अन्य मुद्दों में भाग गया, इसलिए मैंने इस परियोजना के लिए अब ऐप इंजन छोड़ दिया। मुझे यकीन नहीं था कि किसी भी उत्तर को सही के रूप में चिह्नित करना है, लेकिन डेविड के पास सफलता का सबसे अधिक मौका था, इसलिए मैंने उसे चिह्नित किया। डर है कि मैं आपकी मदद नहीं कर सकता हालांकि। यदि आप इसे समझते हैं तो कृपया यहां एक टिप्पणी छोड़ दें ताकि मैं आपके समाधान का भी प्रयास कर सकूं। – tijs

+0

पी। स्टैकओवरफ्लो नियम यह निर्धारित करते हैं कि आपका प्रश्न टिप्पणी के रूप में पोस्ट किया जाना चाहिए था। बस तुम इतना जानते हो... :) – tijs

संबंधित मुद्दे