Работа ndb.OR в движке приложения Google

Я работаю над проектом, где мне нужно выполнить операцию ndb.OR в порядке убывания, но для приведенного ниже кода я получаю следующую ошибку:

BadRequestError: первое свойство сортировки должно совпадать со свойством, к которому применяется фильтр неравенства. В вашем запросе первым свойством сортировки является TestNo, но фильтр неравенства находится в Math.

class StudentMarks(ndb.Model):
    Math = ndb.IntegerProperty()
    Science = ndb.IntegerProperty()
    English = ndb.IntegerProperty()
    Social = ndb.IntegerProperty()
    TestNo = ndb.IntegerProperty()

@classmethod
def queryData(cls):
    return cls.query(ndb.OR(ndb.OR(cls.Math > 0, cls.Science > 0),
                     ndb.OR(cls.English > 0 , cls.Social > 0))).order(-cls.TestNo)

Есть ли другой способ реализовать этот метод.


person Yogeendra    schedule 21.11.2013    source источник


Ответы (1)


Не понимая вашего варианта использования, я могу придумать два способа.

  1. Сортировка в памяти постфактум — это не будет масштабироваться, если у вас тысячи сущностей.
  2. Используйте предложение AND и с TestNo в качестве первого фильтра неравенства (например, TestNo > -1) и OR во второй части предложения AND.

Другим подходом может быть изменение или добавление к сохраненным данным, чтобы вы могли использовать фильтры равенства. Кажется, вы ищете различные комбинации математики, естественных наук, английского языка и т. д., которые имеют значение больше 0. Рассмотрите возможность добавления ComputedProperty, в котором хранится логическое значение true для математики, естественных наук и т. д. > 0, и false, если == 0 , то вы можете переписать свой запрос примерно так: (Я использую имя свойства, например hasMath, для вычисляемого свойства)

Вычисляемое свойство будет выглядеть

hasMath = ndb.ComputedProperty(lambda self: self.Math > 0)    

Запрос будет

cls.query(ndb.OR(ndb.OR(cls.hasMath == True, cls.hasScience == True),
                 ndb.OR(cls.hasEnglish == True , cls.hasSocial == True))).order(-cls.TestNo)

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

 hasClass = ndb.ComputedProperty(lambda self: self.Math > 0 or self.Science > 0 or self.English > 0 or self.Social > 0)

Ваш запрос будет

 cls.query(cls.hasClass == True).order(-cls.TestNo)

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

person Tim Hoffman    schedule 21.11.2013
comment
Вы имеете в виду следующее: вернуть cls.query((ndb.AND(cls.TestNo › 0), ndb.OR(ndb.OR(cls.Math › 0, cls.Science › 0), ndb.OR(cls. Английский › 0 , cls.Social › 0)))).order(-cls.TestNo) - person Yogeendra; 21.11.2013
comment
Да что-то подобное. Не уверен, что это даст вам то, что вы хотите, но стоит попробовать, так как теперь вы можете указать требуемый порядок сортировки. - person Tim Hoffman; 21.11.2013
comment
Но, возможно, стоит пересмотреть свой вариант использования и то, как вы храните данные. Потому что вы можете переформулировать свой фильтр, используя фильтры равенства. Смотрите дополнение к моему ответу. - person Tim Hoffman; 21.11.2013
comment
Еще один очевидный вопрос, почему операторы ИЛИ используют несколько операторов ИЛИ. По сути, запрос будет на операторе ИЛИ или, в соответствии с предложением вычисляемого свойства, одно вычисляемое свойство, которое хранит True, если какой-либо из классов имеет значение › 1. - person Tim Hoffman; 21.11.2013
comment
Мне даже нужно целочисленное значение каждого свойства, например: math = 50, science = 30, English = 44 и т. д. в порядке убывания TestNo в качестве результата запроса. - person Yogeendra; 21.11.2013
comment
У вас уже есть целочисленные значения, вычисляемые свойства добавляются. - person Tim Hoffman; 21.11.2013