0

이 데이터 모델을 사용했습니다. (더 나은 방법이 있다면 알려주십시오.) 나는 Club을 가지고 있는데, 많은 사람이 Courses 일 수 있습니다. 이제 클럽의 모든 membersinstructors을 알고 싶습니다. membersinstructorsCourse 모델에 저장되며 Club에는 모델에 대한 참조가 있습니다. Course@property 나에게 괜찮을 것 같다 ..NDB에 관계 값을 효율적으로 저장하는 방법

class Course(ndb.Model): 
    ... 
    instructor_keys = ndb.KeyProperty(kind="User", repeated=True) 
    member_keys = ndb.KeyProperty(kind="User", repeated=True) 

    @property 
    def instructors(self): 
     return ndb.get_multi(self.instructor_keys) 

    @property 
    def members(self): 
     return filter(lambda x: x.is_active, ndb.get_multi(self.member_keys)) 

    def add_instructor(self, instructor): 
     if instructor.key not in self.instructor_keys: 
      self.instructor_keys.append(instructor.key) 
      self.put() 

    def rm_instructor(self, instructor): 
     if instructor.key in self.instructor_keys: 
      self.instructor_keys.remove(instructor.key) 
      self.put() 

    def add_member(self, member): 
     if member.key not in self.member_keys: 
      self.member_keys.append(member.key) 
      self.put() 

    def rm_member(self, member): 
     if member.key in self.member_keys: 
      self.member_keys.remove(member.key) 
      self.put() 

지금

class Club(ndb.Model): 
    ... 
    owners_keys = ndb.KeyProperty(kind="User", repeated=True) 
    course_keys = ndb.KeyProperty(kind="Course", repeated=True) 


    @property 
    def members(self): 
     # TODO: is this correct? efficient? 
     l_members = [] 
     for courses in self.courses: 
      l_members = l_members + courses.members 
     return l_members 

    @property 
    def trainers(self): 
     l_trainers = [] 
     for courses in self.courses: 
      l_trainers = l_trainers + courses.trainers 
     return l_trainers 

    @property 
    def owners(self): 
     return ndb.get_multi(self.owners_keys) 

    @property 
    def courses(self): 
     return filter(lambda x: x.is_active, ndb.get_multi(self.course_keys)) 

    def add_owner(self, owner): 
     if owner.key not in self.owners_keys: 
      self.owner_keys.append(owner.key) 
      self.put() 

    def rm_owner(self, owner): 
     if owner.key in self.owners_keys: 
      self.owner_keys.remove(owner.key) 
      self.put() 

    def add_course(self, course): 
     if course.key not in self.courses_keys: 
      self.course_keys.append(course.key) 
      self.put() 

    def rm_course(self, course): 
     if course.key in self.courses_keys: 
      self.course_keys.remove(course.key) 
      self.put() 

    def membership_type(self, user): 
     if user.key in self.owners_keys: 
      return "OWNER" 
     elif user in self.members: 
      return "MEMBER" 
     elif user in self.trainers: 
      return "TRAINER" 
     else: 
      raise Exception("The user %s is not in the club %s" % (user.id, self.id)) 

를 코드를 참조하십시오. (내가 맞습니까?) 그러나 Club에있는 것은 매우 비효율적 인 것 같습니다. 모든 Courses을 반복하여 memberstrainers을 계산할 때마다 게다가 이러한 메소드는 캐시되지 않고 매번 계산됩니다. 그래서 매우 비싸면.

의견이 있으십니까? instructorsmembersClub에있는 키 목록으로 생각하고 있는데, 누군가를 Course에 추가 할 때마다 클럽을 업데이트하지만 올바른지 확신 할 수 없습니다.

추신 : ndb.get_multifilter을 더 잘 수행 할 수 있나요? 나는 드 정규화 한가는 대신 모델을 정상화하려고 것

답변

1

: 당신은 그냥 일반적으로

class Course(ndb.Model): 
    # all the stuff already there 

    @property 
    def members(self): 
     return CourseInscription.query(CourseInscription.course == self.key) 

같은 것을 추가 할 수 있습니다 다음

class CourseInscription(ndb.Model): 
    member = ndb.KeyProperty(kind='User', required=True) 
    course = ndb.KeyProperty(kind='Course', required=True) 
    is_active = ndb.BooleanProperty(default=True) 

, 내가 선호 그냥 쿼리를 반환하고 호출자가 직접 호출하거나 더 많은 필터링/정렬을 수행하는 대신에 ndb.get_multi을 직접 처리하도록 결정할 수 있습니다.

내가 일반적으로 할 또 다른 좋은 터치 그들의 부모를 사용하여 관계 기관의 ID를 구성하는 것입니다, 그래서 쉽게 완벽하게

class CourseInscription(ndb.Model): 
    # all the other stuff 

    @staticmethod 
    def build_id(user_key, course_key): 
     return '%s/%s' % (user_key.urlsafe(), course_key.urlsafe()) 

# somewhere I can create an inscription like 

CourseInscription(
    id=CourseInscription.build_id(user_key, course_key), 
    user=user_key, course=course_key, is_active=True 
).put() 

# somewhere else I can check if a User is in a Course by just getting... no queries needed 
if ndb.Key(CourseInscription, CourseInscription.build_id(user, course)).get(): 
    # Then the user is in the course! 
else: 
    # then it's not 
+0

감사합니다. 나는 NDB에서 정규화를 사용하고 올바른 접근법인지에 대해 확신하지 못했습니다. 나는 당신에게 내가 그 질문을 돌려줘야한다는 것에 동의합니다. 그러나'self.member_keys'는 키 목록입니다.이 경우 어떻게해야합니까? – EsseTi

+0

'def build_id (user_key, course_key) :'는 자동으로 그 값에 대한 관계의 id를 설정합니까? 또는 put에서 어떻게 작동합니까? – EsseTi

+0

build_id 예제를 생성시 사용하도록 수정했습니다 (물론 Inscription 클래스에서는 물론이 아닙니다) – marianosimone

1

조회 할 수있는 대신의 ID로 GET과 존재를 확인할 수 있습니다 클럽에 소속 된 회원 및 강사에 대한 감각뿐만 아니라 과정에 의해 참조되는 것. 유스 케이스를 생각하면 회원은 클럽에서 제공하는 코스에 가입하기 전에 클럽에 가입해야합니다 (물론 동시에 발생할 수 있음). 매번 강좌를 횡단하지 말고 회원/강사가 직접 (클럽에서) 참조하도록하는 것이 훨씬 더 효율적입니다. 당신의 트레이드 오프는 추가적인 코드 유지 보수로 이루어 지지만,이 경우에는 정당한 것으로 보인다.

활성 코스 필터에 관해서는 클럽의 '활성'코스 목록과 '비활성'코스 목록을 고려할 수 있습니다. 코스가 더 이상 제공되지 않으면 '비활성'목록으로 이동하십시오 (그것을 '활성'목록에서 제거하십시오).

+0

제안 해 주셔서 감사합니다. 실제로 회원 목록에 적합합니다. – EsseTi