FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Firestore: Adding Collection Group queries by schmidt-sebastian · Pull Request #4652 · googleapis/google-cloud-java · GitHub

Firestore: Adding Collection Group queries - #4652

Merged
kolea2 merged 5 commits into
masterfrom
mrschmidt-collectiongroup
May 1, 2019
Merged

Firestore: Adding Collection Group queries#4652
kolea2 merged 5 commits into
masterfrom
mrschmidt-collectiongroup

Conversation

schmidt-sebastian commented Mar 6, 2019
edited
Loading

Copy link
Copy Markdown
Contributor

CollectionGroup queries add support for queries to Firestore that query documents by collection ID rather than by collection path. With this feature, users can now query for documents in collections that share a name, no matter where these collection are located.

This the server port of firebase/firebase-android-sdk#233, meaning there is less input validation (since the backend does most of it for us) and there is no local logic to execute these queries.

Note: This PR is blocked on a backend release.

schmidt-sebastian requested a review from a team March 6, 2019 18:27
googlebot added the cla: yes This human has signed the Contributor License Agreement. label Mar 6, 2019
schmidt-sebastian added the status: blocked Resolving the issue is dependent on other work. label Mar 6, 2019
schmidt-sebastian changed the title Firestore: Adding Collection Group queries Firestore: Adding Collection Group queries (DO NOT MERGE) Mar 6, 2019

codecov Bot commented Mar 6, 2019
edited
Loading

Copy link
Copy Markdown

Codecov Report

Merging #4652 into master will increase coverage by <.01%.
The diff coverage is 93.46%.

@@             Coverage Diff              @@
##             master    #4652      +/-   ##
============================================
+ Coverage     49.67%   49.68%   +<.01%     
- Complexity    22300    22308       +8     
============================================
  Files          2238     2238              
  Lines        221344   221337       -7     
  Branches      24079    24069      -10     
============================================
+ Hits         109949   109967      +18     
+ Misses       102937   102924      -13     
+ Partials       8458     8446      -12
Impacted Files Coverage Δ Complexity Δ
...java/com/google/cloud/firestore/FirestoreImpl.java 83.04% <100%> (+0.83%) 22 <4> (+3) ⬆️
...rc/main/java/com/google/cloud/firestore/Watch.java 91.81% <100%> (ø) 57 <0> (ø) ⬇️
...om/google/cloud/firestore/CollectionReference.java 48.78% <75%> (+1.28%) 10 <6> (+1) ⬆️
...rc/main/java/com/google/cloud/firestore/Query.java 92.53% <94.07%> (+4.8%) 90 <35> (+4) ⬆️
...src/main/java/com/google/cloud/ServiceOptions.java 41.4% <0%> (+0.88%) 26% <0%> (ø) ⬇️
...om/google/cloud/logging/MonitoredResourceUtil.java 50.92% <0%> (+0.92%) 8% <0%> (ø) ⬇️
.../java/com/google/cloud/testing/CommandWrapper.java 96.96% <0%> (+6.06%) 13% <0%> (ø) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d931fac...b873df9. Read the comment docs.

rsgowman left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm with a bunch of nits.


QueryOptions that = (QueryOptions) o;

if (allDescendants != that.allDescendants) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit: Is there reasoning for this order? If not, then consider reordering to match the declaration order. (If certain variables are more likely to differ, that might be a legit reason to prioritize checking those ones in the presence of a tight loop.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is auto-generated code by IntelliJ (and not by AutoValue).

fieldFilters = new ArrayList<>();
fieldOrders = new ArrayList<>();
fieldProjections = new ArrayList<>();
protected static class QueryOptions {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Unless there's a reason not to, you should probably make this class final.

http://go/java-practices/final#classes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I updated this class to use AutoValue.


if (allDescendants != that.allDescendants) {
return false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Consider refactoring to look like this: http://go/java-practices/equals#impl

Specifically:
a) optionally drop the this==o check unless you think it's useful.
b) use instanceof instead of getClass. (Less relevant if you mark this class final.)
c) Instead of using 3 lines per variable, just use ~1 per variable, i.e.:

return (foo == that.foo
   && bar == that.bar
   && ...);

Entirely optional.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

As above, this is auto-generated and now replaced by AutoValue.

fieldFilters = new ArrayList<>();
fieldOrders = new ArrayList<>();
fieldProjections = new ArrayList<>();
protected static class QueryOptions {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Can we just use go/autovalue here? (public link: https://github.com/google/auto/blob/master/value/userguide/index.md)

If we can, it'd cut this down by quite a lot.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I changed this to use AutoValue as suggested. I personally don't consider this an improvement, as it adds a lot of indirection. QueryOptions was treated by me like a value struct, but its immutability was merely by design. With AutoValue and with the migration to ImmutableList, this is now enforced in code.

fieldProjections = new ArrayList<>();
protected static class QueryOptions {

ResourcePath parentPath;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

These instance variables should all be final too. http://go/java-practices/final#fields.

(Or at least final where possible. I'm haven't checked to see if these are reassigned or not. Hopefully mostly not.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

They were reassigned as part of my "builder-light" pattern:

Options newOptions = new Options(oldOptions);
newOptions.foo = bar;

This is no longer applicable.

Query(FirestoreImpl firestore, ResourcePath path) {
this(firestore, path, new QueryOptions());
this.firestore = firestore;
this.options = new QueryOptions(path.getParent(), path.getId());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Seems reasonable, but consider delegating to the private ctor anyway, i.e.:

Query(firestore, path) {
  this(firestore, new QueryOptoins(path.getParent(), path.getId());
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Done.


this.firestore = firestore;
this.path = path;
this.options = queryOptions;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Similarly, consider delegating to the primary ctor. Optional.

Also note that this ctor (and the other one above) could also be rephrased as static factory methods. (Which would allow you to rename them to something other than 'Query'. Whether that's useful or not is up to you.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I made this change, which is now possible thanks to the QueryOptions.Builder. Without it, I had no way to initialize allDescendants.

I opted not to make these factory methods since CollectionReference inherits from Query and I like the consistency of having two constructors rather than one constructor and one factory method.

Query query = firestoreMock.collectionGroup("foo/bar");
fail();
} catch (IllegalArgumentException e) {
assertEquals(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is fine. Personally, I find it slightly over-specified. (I'd just remove the assertEquals entirely.) Feel free to leave as is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Acknowledged.


assertEquals(begin(), requests.get(0));
assertEquals(query(TRANSACTION_ID), requests.get(1));
assertEquals(query(TRANSACTION_ID, false), requests.get(1));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I've forgotten what the second parameter is (and am too lazy to look it up.) Consider one of the options here:
http://go/java-practices/boolean-parameters

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Added /* allDescendants= */ as a comment. Thanks

schmidt-sebastian left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I addressed your feedback and bit the bullet by moving to AutoValue.

fieldFilters = new ArrayList<>();
fieldOrders = new ArrayList<>();
fieldProjections = new ArrayList<>();
protected static class QueryOptions {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I updated this class to use AutoValue.

fieldFilters = new ArrayList<>();
fieldOrders = new ArrayList<>();
fieldProjections = new ArrayList<>();
protected static class QueryOptions {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I changed this to use AutoValue as suggested. I personally don't consider this an improvement, as it adds a lot of indirection. QueryOptions was treated by me like a value struct, but its immutability was merely by design. With AutoValue and with the migration to ImmutableList, this is now enforced in code.

fieldProjections = new ArrayList<>();
protected static class QueryOptions {

ResourcePath parentPath;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

They were reassigned as part of my "builder-light" pattern:

Options newOptions = new Options(oldOptions);
newOptions.foo = bar;

This is no longer applicable.


QueryOptions that = (QueryOptions) o;

if (allDescendants != that.allDescendants) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is auto-generated code by IntelliJ (and not by AutoValue).


if (allDescendants != that.allDescendants) {
return false;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

As above, this is auto-generated and now replaced by AutoValue.

Query(FirestoreImpl firestore, ResourcePath path) {
this(firestore, path, new QueryOptions());
this.firestore = firestore;
this.options = new QueryOptions(path.getParent(), path.getId());

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Done.


this.firestore = firestore;
this.path = path;
this.options = queryOptions;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I made this change, which is now possible thanks to the QueryOptions.Builder. Without it, I had no way to initialize allDescendants.

I opted not to make these factory methods since CollectionReference inherits from Query and I like the consistency of having two constructors rather than one constructor and one factory method.

Query query = firestoreMock.collectionGroup("foo/bar");
fail();
} catch (IllegalArgumentException e) {
assertEquals(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Acknowledged.


assertEquals(begin(), requests.get(0));
assertEquals(query(TRANSACTION_ID), requests.get(1));
assertEquals(query(TRANSACTION_ID, false), requests.get(1));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Added /* allDescendants= */ as a comment. Thanks

schmidt-sebastian force-pushed the mrschmidt-collectiongroup branch from a9946bb to a6d948b Compare March 14, 2019 01:45
sduskis added the api: bigquery Issues related to the BigQuery API. label Mar 19, 2019
sduskis added api: firestore Issues related to the Firestore API. and removed api: bigquery Issues related to the BigQuery API. labels Apr 11, 2019

Copy link
Copy Markdown
Contributor Author

This is no longer blocked and needs sign off from the Yoshi team.

yoshi-automation added the 🚨 critical P0 critical issue. Requires immediate fix label Apr 26, 2019
schmidt-sebastian changed the title Firestore: Adding Collection Group queries (DO NOT MERGE) Firestore: Adding Collection Group queries Apr 27, 2019

chingor13 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Just a question on whether or not to add a getter method. Otherwise, LGTM.

QueryTarget.newBuilder()
.setStructuredQuery(query.buildQuery())
.setParent(query.getResourcePath().getParent().getName())
.setParent(query.options.getParentPath().getName())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Any particular reason for direct field access vs. a getter? We provide getFirestore() on query, but not getOptions().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

options is purely an internal field that is only used inside the client. We could still use a getOptions() here, but I felt that making it package-private was safe enough.

kolea2 merged commit 7f6dc84 into master May 1, 2019
sduskis deleted the mrschmidt-collectiongroup branch May 1, 2019 17:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: firestore Issues related to the Firestore API. cla: yes This human has signed the Contributor License Agreement. 🚨 critical P0 critical issue. Requires immediate fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants


Back | FazBrowse Home | New Git URL