2014-05-21 2 views
0

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

  • поле = значение
  • Поле = Значение
  • Field1 = Значение1 И Field2 = значение2
  • Field1 = Значение1 ИЛИ Field2 = значение2

Но также могут быть вложены так:

  • (Field1 = Value1 OR Field2 = Value2) A ND Поле3 = Значение3

Вложение может быть бесконечно глубоким.

Я начал с моделью, как это:

Criterion 
    Field Name 
    Comparison Operator 
    Comparison Value 

Это позволяет мне выразить простые критерии, такие как «поле = значение».

Как мне связать цепочку Criterion вместе с помощью инструкций AND/OR и как лучше всего обращаться с гнездованием?

FYI (может добавить больше контекста) - это для проекта Rails/Mongoid. У меня есть Document, который embeds_many :criteria. Мне нужно иметь возможность называть Document.criteria_string и перебирать документ по всем критериям и сопоставлять его с одним оператором, учитывающим вложение, цепочку и позиционирование критериев.

Спасибо!

ответ

2

Я думаю, что понимаю, что вы пытаетесь сделать, и лучший способ приблизиться к этому - подумать о своих логических критериях как дереве, где каждый критерий может быть либо листом (и иметь имя, оператор и значение), либо это может быть ссылка на другие критерии. Критерий-критерий должен быть достаточно умным, чтобы обрабатывать различные типы критериев, которые вам нужны. - Лист дерева является одним из ключевого или значения (определяет ключ строки) - Ветвь дерева является сам по себе критерии

Критерии может быть смоделирован как такой

class Criteria 
    include Mongoid::Document 
    field :string, type: String 
    field :operator, type: String 
    embeds_one :name, class_name: 'Criteria' 
    embeds_one :value, class_name: 'Criteria' 

    def criteria_string 
    string || "#{name.criteria_string} #{operator} #{value.criteria_string}" 
    end 
end 

Ключом является чтобы иметь как имя и значение будут еще внедренными критерии и только имеют определенную строку, когда Criteria представляет собой фактическое имя или строку значения

Criteria.new(
    name: Criteria.new(string: 'city'), 
    operator: '!=', 
    value: Criteria.new(string: 'San Francisco') 
).criteria_string 

#=> "city != San Francisco" 
+0

удивительную. Я использовал Mongoids 'recursively_embeds_many' и смог выполнить его аналогично тому, что у вас было выше. Благодаря! – user1032752

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