Как вставить массив в таблицу Postgresql с помощью ActiveRecord? - PullRequest
2 голосов
/ 19 марта 2012

У меня есть active_record настройка для использования базы данных Postgresql.Один из столбцов - это character varying[] (в основном массив varchar).

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

Пример импортируемых данных выглядит следующим образом (с разделителями табуляции):

Col1      Col2     Col3                  Col4
----------------------------------------------
Apple     Pear     Sweet,Round,Green     Fruit

Col3 импортируется как (ruby): col3.split(/,/)который дает мне массив в Ruby.Но active_record взрывается с:

PG :: Ошибка: ОШИБКА: значение массива должно начинаться с "{" или информации о размерах (ActiveRecord :: StatementInvalid)

Как можноЯ правильно вставил этот столбец?
Также иногда col3 будет иметь значение NULL.

Ответы [ 2 ]

2 голосов
/ 16 апреля 2012

Я смог вставить, используя следующий код Ruby:

alternatenames = '{' + s[3].split(/,/).map {|n| '"' + n + '"'}.join(",") + '}'
0 голосов
/ 18 декабря 2013

Проверьте документы Postgres по этому вопросу: http://www.postgresql.org/docs/9.2/static/arrays.html

Вы можете создать экземпляр модели с помощью массива, подобного [: My,: symbols] или ["My", "Strings"], однако это (вмой опыт и форма того, что кажется в документах) сохранит элементы в виде строк.

Search.create(tokens: [{hash: 'value'}, {test: "fails"}])
=> TypeError: can't cast Hash to string

Где как:

[15] pry(main)> Search.create(tokens: [:G, :F])
=> #<Search id: 78, tokens: [:G, :F], created_at: "2013-12-18 06:29:36", updated_at: "2013-12-18 06:29:36">
[16] pry(main)> Search.last
=> #<Search id: 78, tokens: ["G", "F"], created_at: "2013-12-18 06:29:36", updated_at: "2013-12-18 06:29:36">

В моих тестах у меня есть SearchEngine, Search,и срок.

class SearchEngine < ActiveRecord::Base
  has_and_belongs_to_many :terms
  has_many :searches, through: :terms
end

class Term < ActiveRecord::Base
  has_and_belongs_to_many :searches
  has_and_belongs_to_many :searche_engines
end

class Search < ActiveRecord::Base
  has_many :rankings
  has_many :results, through: :rankings
  has_and_belongs_to_many :terms
  has_many :search_engines, through :terms
end


# These work:
# these next two are the way postgrespl says to query against the array. You get the 
Search.where(tokens: '{A,B}')
Search.where(tokens: '{C,D}').first_or_create

[3] pry(main)> Search.where(tokens: ['C','D']).first
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR:  array value must start with "{" or dimension information

[4] pry(main)> Search.where(tokens: '{C,D}').first
=> #<Search id: 77, tokens: ["C", "D"], created_at: "2013-12-18 06:27:24", updated_at: "2013-12-18 06:27:24">

term = "accident"
Search.where("? = ANY (tokens)", term).first
=> #<Search id: 8, tokens: ["accident", "prevention", "safety"], created_at: "2013-12-18 07:48:13", updated_at: "2013-12-18 07:48:13">
Search.create(tokens: [:Aortic, :Any, :Other, :Elements])
Search.where("'Aortic' = ANY (tokens)").first
Parent.first.first_relationships.first.second_.where("'smelly' = ANY (tokens)").first
# The next one will create one with an empty array for tokens and push it into Term.searches anyway. Same thing with 'smelly'
Term.first.searches.where("':smelly' = ANY (tokens)").first_or_create do |s|   Term.first.searches << s 
end

# These error
Search.where(tokens: "Aortic").first
Search.where(tokens: [:Aortic, :Any, :Other, :Elements]).first

Кроме того, если у вас есть вложенные массивы, вы можете выполнить поиск where с помощью этого: '{{1,2,3}, {4,5,6}, {7,8,9}} 'чтобы найти строку со значением столбца [[1,2,3], [4,5,6], [7,8,9]]

...