sql >> Database teknologi >  >> RDS >> Mysql

Opbygning af forespørgsler dynamisk i skinner

Du kan oprette en SQL-forespørgsel baseret på din hash. Den mest generiske tilgang er rå SQL, som kan udføres af ActiveRecord .

Her er noget konceptkode, der burde give dig den rigtige idé:

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

Hvad dette gør:

  • query_select angiver, hvilke oplysninger du ønsker i resultatet
  • query_where bygger alle søgebetingelser og undslipper input for at forhindre SQL-injektioner
  • query_tables er en liste over alle de tabeller, du skal søge i
  • table_name = table.constantize.table_name vil give dig SQL-tabelnavnet som brugt af modellen
  • raw_query er den faktiske kombinerede sql-forespørgsel fra delene ovenfor
  • ActiveRecord::Base.connection.execute(raw_query) udfører sql på databasen

Sørg for at sætte ethvert brugerindsendt input i anførselstegn og undgå det korrekt for at forhindre SQL-injektioner.

For dit eksempel vil den oprettede forespørgsel se sådan ud:

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

Denne tilgang kræver muligvis yderligere logik for at forbinde tabeller, der er relaterede. I dit tilfælde, hvis company og category har en tilknytning, skal du tilføje noget som dette til query_where

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

Nem tilgang: Du kan oprette en Hash for alle par af modeller/tabeller, der kan forespørges på, og gemme den passende forbindelsestilstand der. Denne Hash bør ikke være for kompleks, selv for et mellemstort projekt.

Hård tilgang: Dette kan gøres automatisk, hvis du har has_many , has_one og belongs_to korrekt defineret i dine modeller. Du kan få tilknytningerne til en model ved at bruge reflect_on_all_associations . Implementer en Breath-First-Search eller Depth-First Search algoritme og start med en hvilken som helst model og søg efter matchende associationer til andre modeller fra din json-input. Start nye BFS/DFS-kørsler, indtil der ikke er nogen ubesøgte modeller tilbage fra json-inputtet. Ud fra de fundne oplysninger kan du udlede alle joinbetingelser og derefter tilføje dem som udtryk i where klausul af raw sql-tilgangen som forklaret ovenfor. Endnu mere komplekst, men også muligt, ville være at læse databasens schema og bruge en lignende tilgang som defineret her ved at lede efter foreign keys .

Brug af tilknytninger: Hvis alle er forbundet med has_many / has_one , kan du håndtere joins med ActiveRecord ved at bruge joins metode med inject på den "mest betydningsfulde" model som denne:

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

Hvad dette gør:

  • den sender base_modellen som startinput til Enumerable.inject , som gentagne gange kalder input.send(:joins, :assoc) (for mit eksempel ville dette gøre Company.send(:joins, :categories) hvilket svarer til `Company.categories
  • på den kombinerede join udfører den where-betingelserne (konstrueret som beskrevet ovenfor)

Ansvarsfraskrivelse Den nøjagtige syntaks, du har brug for, kan variere baseret på den SQL-implementering, du bruger.



  1. PDO - Fatal fejl:Kald til en medlemsfunktion fetch() på et ikke-objekt

  2. Hvordan får man mysqli connect til at fungere?

  3. Vores mest populære database blogindlæg i 2017

  4. SSRS 2014 rapport implementeringsproblem