Как получить строки в виде массивов (не хэшей) в Sequel ORM?

#ruby #sequel

#ruby #продолжение

Вопрос:

В Sequel ORM для Ruby у Dataset класса есть all метод, который создает массив хэшей строк: каждая строка представляет собой хэш с именами столбцов в качестве ключей.

Например, учитывая таблицу T:

 a  b   c
--------------
0  22  "Abe"
1  35  "Betty"
2  58  "Chris"
  

затем:

 ds = DB['select a, b, c from T']
ah = ds.all # Array of row Hashes
  

должно выдавать:

 [{"a":0,"b":22,"c":"Abe"},{"a":1,"b":35,"c":"Betty"},{"a":2,"b":58,"c":"Chris"}]
  

Есть ли встроенный способ продолжить, чтобы вместо этого создать массив массивов строк, где каждая строка представляет собой массив только значений в каждой строке в порядке, указанном в запросе? Вроде как select_rows работает в ActiveRecord? Что-то вроде этого:

 aa = ds.rows # Array of row Arrays
  

что привело бы к:

 [[0,22,"Abe"],[1,35,"Betty"],[2,58,"Chris"]]
  

Примечание: выражение:

 aa = ds.map { |h| h.values }
  

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

 [["Abe",0,22],["Betty",1,35],["Chris",2,58]]
  

Ответ №1:

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

 DB.synchronize do |conn|
  rows = conn.exec('SQL Here') # Hypothetical example code
end
  

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

Комментарии:

1. @jwfeam: Я поддерживаю это. Я не могу стереть улыбку со своего лица с тех пор, как обнаружил это. Наконец -то, что позволяет мне написать именно тот запрос, который мне нужен, без объединения фрагментов строк SQL.

Ответ №2:

DB[:table].where().select_map(:id)

Комментарии:

1. Должен быть принят ответ. my_keys = [:a, :b, :c]; DB[:T].select_map(my_keys)

Ответ №3:

Если вам нужен просто массив значений array…

 DB['select * from T'].map { |h| h.values }
  

кажется, работает

ОБНОВЛЕНИЕ с учетом обновленного требования к порядку столбцов, соответствующему порядку запроса…

 cols= [:a, :c, :b]
DB[:T].select{cols}.collect{ |h| cols.collect {|c| h[c]}}
  

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

Комментарии:

1. Это создает массив, но, в отличие от ActiveRecord select_rows , порядок столбцов не обязательно соответствует порядку, запрошенному в базовом запросе. Я отредактирую свой вопрос, чтобы указать это требование.

2. Я думаю, что если вы хотите гарантировать порядок, то вам нужно указать столбцы, которые вы хотите получить, по порядку, используя dataset#select{[columns,..]} , я дополню свой ответ примером.

3. К вашему сведению, это, конечно, завершится неудачей, если в вашем результирующем наборе будут дублироваться имена столбцов: DB['SELECT 1 AS test, 2 AS test']

Ответ №4:

Я еще не нашел встроенный метод для возврата массива массивов строк, где значения в массивах строк упорядочены по порядку столбцов в исходном запросе. Следующая функция выполняет * хотя я подозреваю, что внутренний метод мог бы быть более эффективным:

 def rows( ds )
  ret = []
  column_keys = ds.columns  # guaranteed to match query order?
  ds.all { |row_hash|
    row_array = []
    column_keys.map { |column_key| row_array << row_hash[column_key] }
    ret << row_array
  }
  ret
end
  

* Эта функция зависит от порядка массива, возвращаемого Dataset.columns . Если этот порядок не определен, то эта rows функция не очень полезна.

Ответ №5:

вы пробовали это?

 ds = DB['select a, b, c from T'].to_a
  

не уверен, что это работает, но попробуйте.