From 5a14fd6cca94e40bad913e3662a6c0a2dabaa33e Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Mon, 24 Feb 2020 11:06:15 -0700 Subject: [PATCH] feat(firestore): Add IN and ARRAY_CONTAINS_ANY query operators closes: #4745 pr: #4823 --- .../acceptance/firestore/query_test.rb | 18 +++- .../lib/google/cloud/firestore/query.rb | 39 +++++---- .../query/where/array_contains_any_test.rb | 78 +++++++++++++++++ .../cloud/firestore/query/where/in_test.rb | 84 +++++++++++++++++++ 4 files changed, 200 insertions(+), 19 deletions(-) create mode 100644 google-cloud-firestore/test/google/cloud/firestore/query/where/array_contains_any_test.rb create mode 100644 google-cloud-firestore/test/google/cloud/firestore/query/where/in_test.rb diff --git a/google-cloud-firestore/acceptance/firestore/query_test.rb b/google-cloud-firestore/acceptance/firestore/query_test.rb index 96515a015758..5ccc62308b4c 100644 --- a/google-cloud-firestore/acceptance/firestore/query_test.rb +++ b/google-cloud-firestore/acceptance/firestore/query_test.rb @@ -39,7 +39,7 @@ result_snp[:foo].must_equal "bar" end - it "has where method with array_contains " do + it "has where method with array_contains" do rand_query_col = firestore.col "#{root_path}/query/#{SecureRandom.hex(4)}" rand_query_col.add({foo: ["bar", "baz", "bif"]}) @@ -47,6 +47,22 @@ result_snp[:foo].must_equal ["bar", "baz", "bif"] end + it "has where method with in" do + rand_query_col = firestore.col "#{root_path}/query/#{SecureRandom.hex(4)}" + rand_query_col.add({foo: "bar"}) + + result_snp = rand_query_col.where(:foo, :in, ["bar", "baz", "bif"]).get.first + result_snp[:foo].must_equal "bar" + end + + it "has where method with array_contains_any" do + rand_query_col = firestore.col "#{root_path}/query/#{SecureRandom.hex(4)}" + rand_query_col.add({foo: ["bar", "baz", "bif"]}) + + result_snp = rand_query_col.where(:foo, :array_contains_any, [:bif, :out]).get.first + result_snp[:foo].must_equal ["bar", "baz", "bif"] + end + it "supports NaN" do rand_query_col = firestore.col "#{root_path}/query/#{SecureRandom.hex(4)}" doc_ref = rand_query_col.add({foo: Float::NAN}) diff --git a/google-cloud-firestore/lib/google/cloud/firestore/query.rb b/google-cloud-firestore/lib/google/cloud/firestore/query.rb index 122b25b2ebb4..2e141512c2e5 100644 --- a/google-cloud-firestore/lib/google/cloud/firestore/query.rb +++ b/google-cloud-firestore/lib/google/cloud/firestore/query.rb @@ -888,24 +888,27 @@ def self.start query, parent_path, client ## # @private FILTER_OPS = { - "<" => :LESS_THAN, - "lt" => :LESS_THAN, - "<=" => :LESS_THAN_OR_EQUAL, - "lte" => :LESS_THAN_OR_EQUAL, - ">" => :GREATER_THAN, - "gt" => :GREATER_THAN, - ">=" => :GREATER_THAN_OR_EQUAL, - "gte" => :GREATER_THAN_OR_EQUAL, - "=" => :EQUAL, - "==" => :EQUAL, - "eq" => :EQUAL, - "eql" => :EQUAL, - "is" => :EQUAL, - "array_contains" => :ARRAY_CONTAINS, - "array-contains" => :ARRAY_CONTAINS, - "include" => :ARRAY_CONTAINS, - "include?" => :ARRAY_CONTAINS, - "has" => :ARRAY_CONTAINS + "<" => :LESS_THAN, + "lt" => :LESS_THAN, + "<=" => :LESS_THAN_OR_EQUAL, + "lte" => :LESS_THAN_OR_EQUAL, + ">" => :GREATER_THAN, + "gt" => :GREATER_THAN, + ">=" => :GREATER_THAN_OR_EQUAL, + "gte" => :GREATER_THAN_OR_EQUAL, + "=" => :EQUAL, + "==" => :EQUAL, + "eq" => :EQUAL, + "eql" => :EQUAL, + "is" => :EQUAL, + "array_contains" => :ARRAY_CONTAINS, + "array-contains" => :ARRAY_CONTAINS, + "include" => :ARRAY_CONTAINS, + "include?" => :ARRAY_CONTAINS, + "has" => :ARRAY_CONTAINS, + "in" => :IN, + "array_contains_any" => :ARRAY_CONTAINS_ANY, + "array-contains-any" => :ARRAY_CONTAINS_ANY }.freeze ## # @private diff --git a/google-cloud-firestore/test/google/cloud/firestore/query/where/array_contains_any_test.rb b/google-cloud-firestore/test/google/cloud/firestore/query/where/array_contains_any_test.rb new file mode 100644 index 000000000000..ec60be0948ed --- /dev/null +++ b/google-cloud-firestore/test/google/cloud/firestore/query/where/array_contains_any_test.rb @@ -0,0 +1,78 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" + +describe Google::Cloud::Firestore::Query, :where, :array_contains_any, :mock_firestore do + let(:query) { Google::Cloud::Firestore::Query.start nil, "#{firestore.path}/documents", firestore } + + it "using array-contains-any" do + expected_query = Google::Firestore::V1::StructuredQuery.new( + where: Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :ARRAY_CONTAINS_ANY, + value: Google::Firestore::V1::Value.new(integer_value: 42) + ) + ) + ) + + generated_query = query.where(:foo, "array-contains-any", 42).query + generated_query.must_equal expected_query + end + + it "using array_contains_any" do + expected_query = Google::Firestore::V1::StructuredQuery.new( + where: Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :ARRAY_CONTAINS_ANY, + value: Google::Firestore::V1::Value.new(integer_value: 42) + ) + ) + ) + + generated_query = query.where(:foo, :array_contains_any, 42).query + generated_query.must_equal expected_query + end + + it "with multiple values" do + expected_query = Google::Firestore::V1::StructuredQuery.new( + where: Google::Firestore::V1::StructuredQuery::Filter.new( + composite_filter: Google::Firestore::V1::StructuredQuery::CompositeFilter.new( + op: :AND, + filters: [ + Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :ARRAY_CONTAINS_ANY, + value: Google::Firestore::V1::Value.new(integer_value: 42) + ) + ), + Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :ARRAY_CONTAINS_ANY, + value: Google::Firestore::V1::Value.new(integer_value: 43) + ) + ) + ] + ) + ) + ) + + generated_query = query.where(:foo, :array_contains_any, 42).where(:foo, :array_contains_any, 43).query + generated_query.must_equal expected_query + end +end diff --git a/google-cloud-firestore/test/google/cloud/firestore/query/where/in_test.rb b/google-cloud-firestore/test/google/cloud/firestore/query/where/in_test.rb new file mode 100644 index 000000000000..153ba3f28cdf --- /dev/null +++ b/google-cloud-firestore/test/google/cloud/firestore/query/where/in_test.rb @@ -0,0 +1,84 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" + +describe Google::Cloud::Firestore::Query, :where, :array_contains_any, :mock_firestore do + let(:query) { Google::Cloud::Firestore::Query.start nil, "#{firestore.path}/documents", firestore } + + it "using in" do + expected_query = Google::Firestore::V1::StructuredQuery.new( + where: Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :IN, + value: Google::Firestore::V1::Value.new( + array_value: Google::Firestore::V1::ArrayValue.new( + values: [ + Google::Firestore::V1::Value.new(integer_value: 42), + Google::Firestore::V1::Value.new(integer_value: 43) + ] + ) + ) + ) + ) + ) + + generated_query = query.where(:foo, :in, [42, 43]).query + generated_query.must_equal expected_query + end + + it "with multiple values" do + expected_query = Google::Firestore::V1::StructuredQuery.new( + where: Google::Firestore::V1::StructuredQuery::Filter.new( + composite_filter: Google::Firestore::V1::StructuredQuery::CompositeFilter.new( + op: :AND, + filters: [ + Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :IN, + value: Google::Firestore::V1::Value.new( + array_value: Google::Firestore::V1::ArrayValue.new( + values: [ + Google::Firestore::V1::Value.new(integer_value: 42), + Google::Firestore::V1::Value.new(integer_value: 43) + ] + ) + ) + ) + ), + Google::Firestore::V1::StructuredQuery::Filter.new( + field_filter: Google::Firestore::V1::StructuredQuery::FieldFilter.new( + field: Google::Firestore::V1::StructuredQuery::FieldReference.new(field_path: "foo"), + op: :IN, + value: Google::Firestore::V1::Value.new( + array_value: Google::Firestore::V1::ArrayValue.new( + values: [ + Google::Firestore::V1::Value.new(integer_value: 43), + Google::Firestore::V1::Value.new(integer_value: 44) + ] + ) + ) + ) + ) + ] + ) + ) + ) + + generated_query = query.where(:foo, :in, [42, 43]).where(:foo, :in, [43, 44]).query + generated_query.must_equal expected_query + end +end