Mysql
 sql >> база данни >  >> RDS >> Mysql

Динамично изграждане на заявки в релсите

Можете да създадете SQL заявка въз основа на вашия хеш. Най-общият подход е необработен SQL, който може да се изпълни от ActiveRecord .

Ето някои концептуален код, който трябва да ви даде правилната идея:

query_select = "select * from "
query_where = ""
tables = [] # for selecting from all tables
hash.each do |table, values|
  table_name = table.constantize.table_name
  tables << table_name
  values.each do |q|
    query_where += " AND " unless query_string.empty?
    query_where += "'#{ActiveRecord::Base.connection.quote(table_name)}'."
    query_where += "'#{ActiveRecord::Base.connection.quote(q[fieldName)}'"
    if q[:operator] == "starts with" # this should be done with an appropriate method
      query_where += " LIKE '#{ActiveRecord::Base.connection.quote(q[val)}%'"
    end
  end
end
query_tables = tables.join(", ")
raw_query = query_select + query_tables + " where " + query_where 
result = ActiveRecord::Base.connection.execute(raw_query)
result.to_h # not required, but raw results are probably easier to handle as a hash

Какво прави това:

  • query_select указва каква информация искате в резултата
  • query_where изгражда всички условия за търсене и избягва въвеждането, за да предотврати SQL инжекции
  • query_tables е списък с всички таблици, които трябва да търсите
  • table_name = table.constantize.table_name ще ви даде SQL table_name, както се използва от модела
  • raw_query е действителната комбинирана sql заявка от частите по-горе
  • ActiveRecord::Base.connection.execute(raw_query) изпълнява sql в базата данни

Уверете се, че сте поставили всички въведени от потребителя данни в кавички и ги екранирайте правилно, за да предотвратите SQL инжекции.

За вашия пример създадената заявка ще изглежда така:

select * from companies, categories where 'companies'.'name' LIKE 'a%' AND 'companies'.'hq_city' = 'karachi' AND 'categories'.'name' NOT LIKE '%ECommerce%'

Този подход може да се нуждае от допълнителна логика за свързване на свързани таблици. Във вашия случай, ако company и category ако имате асоциация, трябва да добавите нещо подобно към query_where

"AND 'company'.'category_id' = 'categories'.'id'"

Лесен подход: Можете да създадете хеш за всички двойки модели/таблици, които могат да бъдат запитани и да съхранявате подходящото условие за присъединяване там. Този хеш не трябва да е твърде сложен дори за среден проект.

Труден подход: Това може да стане автоматично, ако имате has_many , has_one и belongs_to правилно дефинирани във вашите модели. Можете да получите асоциациите на модел, като използвате reflect_on_all_associations /a> . Реализирайте Breath-First-Search или Depth-First Search алгоритъм и започнете с всеки модел и потърсете съвпадащи асоциации с други модели от вашия json вход. Стартирайте нови работи на BFS/DFS, докато не останат непосетени модели от json входа. От намерената информация можете да извлечете всички условия за присъединяване и след това да ги добавите като изрази в where клауза на необработения sql подход, както е обяснено по-горе. Още по-сложно, но и изпълнимо би било четенето на schema на базата данни и използвайки подобен подход, както е дефиниран тук, като търсите foreign keys .

Използване на асоциации: Ако всички те са свързани с has_many / has_one , можете да обработвате обединяванията с ActiveRecord с помощта на joins метод с inject на "най-значимия" модел като този:

base_model = "Company".constantize
assocations = [:categories]  # and so on
result = assocations.inject(base_model) { |model, assoc| model.joins(assoc) }.where(query_where)

Какво прави това:

  • той предава base_model като начален вход към Enumerable.inject , което многократно ще извиква input.send(:joins, :assoc) (за моя пример това ще направи Company.send(:joins, :categories) което е еквивалентно на `Company.categories
  • при комбинираното съединение той изпълнява условията where (конструирани, както е описано по-горе)

Отказ от отговорност Точният синтаксис, от който се нуждаете, може да варира в зависимост от SQL реализацията, която използвате.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Защо препратките към wp_postmeta са толкова бавни?

  2. Изпълнете PDO с масив, съдържащ нулеви стойности

  3. Постигнете йерархия, взаимоотношения родител/дете по ефективен и лесен начин

  4. mysql като повишаване на производителността

  5. DATEDIFF() Примери – MySQL