· 8 years ago · Mar 04, 2018, 12:22 AM
1ActiveRecord::Base.connection.execute('DROP TABLE IF EXISTS non_duplicate_cat_typles')
2
3ActiveRecord::Base.connection.execute(<<-SQL)
4 CREATE TABLE non_duplicate_cat_typles (
5 id serial primary key,
6 main_id integer NOT NULL,
7 non_duplicate_id integer NOT NULL
8 );
9SQL
10
11class NonDuplicateTyples < ActiveRecord::Base
12end
13
14class NonDuplicates
15 # include SqlImplementation
16 # include RubyImplementation
17 def non_duplicates
18 raise 'Implement me!'
19 end
20
21 def include?(*typle)
22 raise 'Implement me!'
23 end
24end
25
26not_duplicates = NonDuplicates.new
27cat_duplicates = []
28# We have a place where
291.upto(100_000).each do |remote_cat_id|
30 1.upto(100_000).each do |cat_id|
31 next if not_duplicates.include?(cat_id, remote_cat_id)
32 # we need to check if the
33 cat_duplicates << [remote_cat_id, cat_id]
34 end
35end
36
37# We were wondering about two implementations of NonDuplicates and we call them with
38# naive names SqlImplementation and RubyImplementation
39
40module SqlImplementation
41 def not_duplicates
42 return @not_duplicates if @not_duplicates
43
44 result =
45 connection.execute <<-SQL
46 WITH all_non_duplicates AS (
47 SELECT main_id AS main, non_duplicate_id AS non_duplicate
48 FROM non_duplicate_cat_typles
49
50 UNION
51
52 SELECT non_duplicate_id AS main, main_id AS non_duplicate
53 FROM non_duplicate_cat_typles
54 )
55 SELECT main, array_agg(non_duplicate) FROM all_non_duplicates GROUP BY main;
56 SQL
57
58 @not_duplicates =
59 result.
60 values.
61 to_h.
62 transform_values { |v| PG::TextDecoder::Array.new.decode(v).map(&:to_i) }
63 end
64
65 def include?(first_id, second_id)
66 @not_duplicates[first_id]&.include?(second_id)
67 end
68end
69
70module RubyImplementation
71 def not_duplicates
72 @not_duplicates =
73 NonDuplicateTyples.
74 pluck(:main_id, :non_duplicate_id).
75 map(&:to_set).
76 to_set
77 end
78end