1

Я создал базу данных продуктов, которая разделена на 3 части. И каждая часть имеет «под» часть, содержащую метки. Но чем больше я работаю с ним, тем более неустойчивым он чувствует. И каждое добавление, которое я делаю, требует больше и больше кода, чтобы заставить его работать.Разработка масштабируемой базы данных продуктов в Google App Engine

Продукт изготовлен из деталей, и каждая деталь имеет тип. Каждый продукт, часть и тип имеет ярлык. И есть этикетка для каждого языка.

Продукт содержит детали в 2-х списках. Один список для частей по умолчанию (один из каждого типа) и одна из дополнительных частей.

Теперь я хочу добавить валюту в микс и пришла к решению перемоделировать весь способ, которым я справляюсь с этим.

В результате я хочу получить список всех объектов продукта, который содержит имя, описание, цену, все детали и все типы, соответствующие деталям. И для них правильные метки языка.

Как так:

product 
    - name 
    - description (by language) 
    - price (by currency) 
    - parts 
     - part (type name and part name by language) 
     - partPrice (by currency) 

Проблема с моей текущей настройки, что это дикая смесь из db.ReferenceProperty и db.ListProperty (db.key)

И получать все данные, немного сложности, требующие нескольких циклов for-loops, соответствующих вызовам dict и datastore. Ну, это немного беспорядок.

Повторная модель (не проверенная) выглядеть следующим образом

class Products(db.model) 
    name = db.StringProperty() 
    imageUrl = db.StringProperty() 
    optionalParts = db.ListProperty(db.Key) 
    defaultParts = db.ListProperty(db.Key) 
    active = db.BooleanProperty(default=True) 

    @property 
    def itemId(self): 
     return self.key().id() 

class ProductPartTypes(db.Model): 
    name= db.StringProperty() 

    @property 
    def itemId(self): 
     return self.key().id() 

class ProductParts(db.Model):  
    name = db.StringProperty() 
    type = db.ReferenceProperty(ProductPartTypes) 
    imageUrl = db.StringProperty() 
    parts = db.ListProperty(db.Key) 

    @property 
    def itemId(self): 
     return self.key().id() 


class Labels(db.Model) 
    key = db.StringProperty() #want to store a key here 
    language = db.StringProperty() 
    label = db.StringProperty() 

class Price(db.Model) 
    key = db.StringProperty() #want to store a key here 
    language = db.StringProperty() 
    price = db.IntegerProperty() 

Главное, здесь в том, что я разделить этикетки и Цены вне. Таким образом, они могут содержать этикетки и цены для любых продуктов, деталей или типов.

Итак, что мне интересно, это прочное решение с архитектурной точки зрения? Будет ли это выполнено, даже если в каждой модели тысячи записей?

Также приветствуются любые советы по извлечению данных. Мое текущее решение: сначала получить все данные и зациклиться на них, а также наклеить их на диктофоны, но похоже, что это может провалиться в любую минуту.

..fredrik

ответ

1

IMO ваш дизайн в основном имеет смысл. Я придумал почти такой же дизайн после прочтения вашего заявления о проблеме. С несколькими отличиями

  • У меня были цены с Продуктом и ПродуктомПодробнее, чем отдельная таблица.
  • Другая разница была part_types. Если их не так много, вы можете просто использовать их как список/кортеж python.

part_types = ('wheel', 'break', 'mirror')

Это также зависит от вида запросов вы опережающими. Если есть много запросов о расчете цены на природу (независимо от остальной части продукта и информации о деталях), тогда может возникнуть смысл разработать его так, как вы это сделали.

Вы упомянули, что сначала получите все данные. Не спрашивать? Если вы получаете все данные в своем приложении, а затем сортируете/фильтруете в python, это будет медленным. Какую базу данных вы рассматриваете? Для меня mongodb выглядит неплохо.

Наконец, почему вы подозреваете, что даже 1000 записей? Вы можете выполнить несколько тестов на своем db заранее.

Bests

+0

Спасибо. Причиной отдельной цены является то, что продукт содержит одну цену для каждого языка (валюты) и тот же для типов. Каждый тип имеет метку на основе текущего языка. Есть ли способ использовать кортеж с некоторой поддержкой языка? – fredrik

+0

Я хочу получить все данные один раз (по крайней мере один для каждой таблицы), поэтому я не заканчиваю upp с помощью нового запроса, например, для получения метки для продукта при переходе по ним. – fredrik

+0

Правильный подход IMO заключается в сохранении цены в десятичной форме, а затем вы должны использовать соответствующую утилиту фрейма для отображения в желаемом формате валюты. – Shekhar

3

Вы должны иметь в виду, что хранилище данных App Engine необходимо, чтобы вы пересмотрите свой обычный способ проектирования баз данных. Сначала это противоречит интуиции, но вы должны как можно больше денормализовать свои данные, если хотите, чтобы ваше приложение было масштабируемым. Это хранилище данных было создано таким образом.

Подход, который я обычно предпринимаю, состоит в том, чтобы сначала рассмотреть, какие запросы нужно будет выполнять в разных вариантах использования, например. какие данные мне нужно получить в одно и то же время? В каком порядке? Какие свойства должны быть проиндексированы?

Если я правильно понимаю, ваша основная цель - получить список продуктов с полной информацией. BTW, если у вас есть другие сценарии запросов - то есть. фильтрация по цене, типу и т. д. - вы должны учитывать их также.

Для того, чтобы извлечь все данные, необходимые только из одного запроса, я предлагаю вам создать одну модель, которая может выглядеть следующим образом:

class ProductPart(db.Model): 
    product_name = db.StringProperty() 
    product_image_url = db.StringProperty() 
    product_active = db.BooleanProperty(default=True) 
    product_description = db.StringListProperty(indexed=False) # Contains product description in all languages 
    part_name = db.StringProperty() 
    part_image_url = db.StringProperty() 
    part_type = db.StringListProperty(indexed=False) # Contains part type in all languages 
    part_label = db.StringListProperty(indexed=False) # Contains part label in all languages 
    part_price = db.ListProperty(float, indexed=False) # Contains part price in all currencies 
    part_default = db.BooleanProperty() 
    part_optional = db.BooleanProperty() 

Об этом решении:

  • ListProperties установлены до indexed = False, чтобы избежать взрывоопасных индексов, если вам не нужно для их фильтрации.
  • Для того, чтобы получить правильное обозначение , вам необходимо установить все значения в том же порядке. Например: part_label [0] is Английский, part_label [1] является испанским, и т. Д. То же самое касается цен и валют.
  • После извлечения объектов из этой модели вы должны сделать некоторые в памяти манипуляции для того, чтобы получить данные хорошо структурирован путь вы хотите, может быть в новом словаре.

Очевидно, что в таком хранилище будет много избыточности в хранилище данных, но это нормально, поскольку это позволяет вам запрашивать хранилище данных масштабируемым образом.

Кроме того, это не означает замену архитектуры, которую вы имели в виду, а скорее дополнительную модель, разработанную специально для запросов пользователей, которые вам нужно выполнить, т.е. получение списков полной информации о товарах/деталях.

Эти объекты ProductPart могут быть заполнены фоновыми задачами, реплицируя данные, расположенные в других нормализованных объектах, которые будут авторитетным источником данных. Поскольку у вас много хранилища данных в App Engine, это не должно быть проблемой.

+0

Мне очень нравится идея фона! Я думаю о комбинированном решении. Мое решение, которое содержит логику и твою исходную задачу, применяет ее, как описано. Затем результат попытается получить денормализованные данные, если он существует, или сделать запрос против моих моделей. Что такое взрывающиеся индексы? – fredrik

+0

пс. Спасибо за исправление моей орфографии и грамматики :) – fredrik

+1

Вот некоторая информация о взрывающихся индексах: http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Big_Entities_and_Exploding_Indexes – Franck

Смежные вопросы