@@ -15,16 +15,19 @@ if Code.ensure_loaded?(Ecto) do
15
15
a_after = cursor_to_offset ( args [ :after ] )
16
16
first = args [ :first ]
17
17
last = args [ :last ]
18
+ where_property = args [ :where ] || :id
18
19
limit = Enum . min ( [ first , last , connection_count ( repo , query ) ] )
19
20
20
21
query = if a_after do
21
- from things in query , where: things . inserted_at > ^ a_after
22
+ frag = [ { where_property , [ >: a_after ] } ]
23
+ query |> where ( fragment ( ^ frag ) )
22
24
else
23
25
query
24
26
end
25
27
26
28
query = if before do
27
- from things in query , where: things . inserted_at < ^ before
29
+ frag = [ { where_property , [ <: before ] } ]
30
+ query |> where ( fragment ( ^ frag ) )
28
31
else
29
32
query
30
33
end
@@ -49,13 +52,13 @@ if Code.ensure_loaded?(Ecto) do
49
52
end
50
53
51
54
query = if first do
52
- from things in query , order_by: [ asc: things . inserted_at ] , limit: ^ limit
55
+ query |> order_by ( asc: ^ where_property ) |> limit ( ^ limit )
53
56
else
54
57
query
55
58
end
56
59
57
60
query = if last do
58
- from things in query , order_by: [ desc: things . inserted_at ] , limit: ^ limit
61
+ query |> order_by ( desc: ^ where_property ) |> limit ( ^ limit )
59
62
else
60
63
query
61
64
end
@@ -64,7 +67,7 @@ if Code.ensure_loaded?(Ecto) do
64
67
65
68
edges = Enum . map ( records , fn ( record ) ->
66
69
% {
67
- cursor: cursor_for_object_in_connection ( record ) ,
70
+ cursor: cursor_for_object_in_connection ( record , where_property ) ,
68
71
node: record
69
72
}
70
73
end )
@@ -92,19 +95,23 @@ if Code.ensure_loaded?(Ecto) do
92
95
def cursor_to_offset ( cursor ) do
93
96
case Base . decode64 ( cursor ) do
94
97
{ :ok , decoded_cursor } ->
95
- date_string = String . slice ( decoded_cursor , String . length ( @ prefix ) .. String . length ( decoded_cursor ) )
96
- case Ecto.DateTime . cast ( date_string ) do
98
+ string = String . slice ( decoded_cursor , String . length ( @ prefix ) .. String . length ( decoded_cursor ) )
99
+ case Ecto.DateTime . cast ( string ) do
97
100
{ :ok , date } -> date
98
- _ -> nil
101
+ :error -> string
99
102
end
100
103
:error ->
101
104
nil
102
105
end
103
106
end
104
107
105
- def cursor_for_object_in_connection ( object ) do
106
- date_string = Ecto.DateTime . to_iso8601 ( object . inserted_at )
107
- Base . encode64 ( "#{ @ prefix } #{ date_string } " )
108
+ def cursor_for_object_in_connection ( object , property \\ :id ) do
109
+ prop = case Map . get ( object , property ) do
110
+ % Ecto.DateTime { } = date_time -> Ecto.DateTime . to_iso8601 ( date_time )
111
+ prop -> to_string ( prop )
112
+ end
113
+
114
+ Base . encode64 ( "#{ @ prefix } #{ prop } " )
108
115
end
109
116
110
117
def connection_count ( repo , query ) do
@@ -117,6 +124,7 @@ if Code.ensure_loaded?(Ecto) do
117
124
query
118
125
|> remove_select
119
126
|> remove_order
127
+ |> remove_preload
120
128
end
121
129
122
130
# Remove select if it exists so that we avoid `only one select
@@ -130,5 +138,11 @@ if Code.ensure_loaded?(Ecto) do
130
138
defp remove_order ( query ) do
131
139
Ecto.Query . exclude ( query , :order_by )
132
140
end
141
+
142
+ # Remove preload if it exists so that we avoid unnecessary joins
143
+ # when trying to retrieve a count
144
+ defp remove_preload ( query ) do
145
+ Ecto.Query . exclude ( query , :preload )
146
+ end
133
147
end
134
148
end
0 commit comments