-
Notifications
You must be signed in to change notification settings - Fork 627
Pipelines Implementation #6710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/pipelines
Are you sure you want to change the base?
Pipelines Implementation #6710
Conversation
Test Results 8 files 8 suites 1m 0s ⏱️ Results for commit f579bf4. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review is WIP. There is lots of great cleanup in this. Nice work. Only a few comments so far.
@@ -120,6 +120,15 @@ public String getPath() { | |||
return key.getPath().canonicalString(); | |||
} | |||
|
|||
@RestrictTo(RestrictTo.Scope.LIBRARY) | |||
@NonNull | |||
public String getFullPath() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should javadocs for RestrictTo Library indicate that status? Or will this be visible even without use of the linter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should restrict visibility from my understanding.
fun replace(field: String): Pipeline = replace(Expr.field(field)) | ||
|
||
/** | ||
* Fully overwrites all fields in a document with those coming from a nested map. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think this has to be a nested map, it can be any expression that evaluates to a map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
unnest(Expr.field(arrayField).alias(alias)) | ||
|
||
/** | ||
* Takes a specified array from the input documents and outputs a document for each element with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, i think this can be any Selectable with an expression that evaluates to an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Takes a specified array" -> "Transforms an array expression" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really impressive code. I learned a lot about kotlin. I'm offering a handful of questions and comments.
|
||
companion object { | ||
|
||
@JvmStatic fun generic(name: String, vararg expr: Expr) = AggregateFunction(name, expr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be raw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so.
* | ||
* @return A new [AggregateFunction] representing the countAll aggregation. | ||
*/ | ||
@JvmStatic fun countAll() = AggregateFunction("count") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the SDK name and server API name match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we discussed this and were sticking to countAll
... but feel free to change in my absence.
@JvmStatic | ||
fun constant(value: Boolean): BooleanExpr { | ||
val encodedValue = encodeValue(value) | ||
return object : BooleanExpr("N/A", emptyArray()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be useful to include some documentation covering the reason why you are creating an anonymous BooleanExpr class here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment
* @return A new [Expr] constant instance representing the Blob. | ||
*/ | ||
@JvmStatic | ||
fun blob(bytes: ByteArray): Expr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible discussion topic, but it might be more clear to indicate in the function name that this will create a Constant Expr. blobConstant(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worthy discussion topic. I tend to agree with you.
I'll leave this in your hands.
* @return A [Expr] constant instance. | ||
*/ | ||
@JvmStatic | ||
fun vector(vector: DoubleArray): Expr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, might be worth naming vectorConstant(...)
or constantVector(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dido
|
||
@JvmField val JSON = OutputFormat("json") | ||
|
||
@JvmField val STRUCT = OutputFormat("struct") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't seen 'struct' in the spec. Is this different from JSON?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whereas JSON is a large string, Struct is the equivalent proto format that takes advantage of protocol buffers to be much smaller. So Struct is the same as JSON, the same way YAML is the same as JSON. They both offer the same expressiveness, in a slightly different format. There are of course nuances, JSON can contain very large numeric since they are stored as strings. And YAML can contain comments.
This is a remnant from an early discussion. So yes, it should be removed for now.
At some point I hope Firestore will concern itself more with wire format, instead of stuffing JSON into protocol buffers. Which I imagine is like stuffing JSON inside a JSON string (which I believe is the case of REST variant of explain)?
} | ||
} | ||
|
||
class Verbosity private constructor(internal val value: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, i haven't seen this in the design. is this new?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
} | ||
} | ||
|
||
class Profiles private constructor(internal val value: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, i haven't seen this in the design. is this new?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
override fun args(userDataReader: UserDataReader): Sequence<Value> = emptySequence() | ||
} | ||
|
||
class CollectionSource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in node, i found that i liked calling all of these *StageOptions. It gave consistency and meaning across the Pipeline api. Maybe you would consider calling these *Stage.
E.g. CollectionStage or CollectionSourceStage, DatabaseStage, LimitStage, WhereStage, ...
fields.asSequence().map(Field::toProto) | ||
} | ||
|
||
internal class ReplaceStage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have intent to make all of these internal stages public to support options overrides?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
Does it need to be done before release? Maybe (your call)
I only exposed the stage classes when the API required it, not just future proofing raw options. Exposing the stages will require also adding constructors / create methods that offer same semantics and documentation as Pipeline API. I wasn't going to do this work until the dust settled on options, and it is not critical for release in my opinion. There is always the rawStage.
Firebase AI Mock Responses Check
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MarkDuckworth I have addressed your feedback. Let me know if there is anything else.
@@ -120,6 +120,15 @@ public String getPath() { | |||
return key.getPath().canonicalString(); | |||
} | |||
|
|||
@RestrictTo(RestrictTo.Scope.LIBRARY) | |||
@NonNull | |||
public String getFullPath() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should restrict visibility from my understanding.
fun replace(field: String): Pipeline = replace(Expr.field(field)) | ||
|
||
/** | ||
* Fully overwrites all fields in a document with those coming from a nested map. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
unnest(Expr.field(arrayField).alias(alias)) | ||
|
||
/** | ||
* Takes a specified array from the input documents and outputs a document for each element with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Takes a specified array" -> "Transforms an array expression" ?
* | ||
* @return A new [AggregateFunction] representing the countAll aggregation. | ||
*/ | ||
@JvmStatic fun countAll() = AggregateFunction("count") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we discussed this and were sticking to countAll
... but feel free to change in my absence.
|
||
companion object { | ||
|
||
@JvmStatic fun generic(name: String, vararg expr: Expr) = AggregateFunction(name, expr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so.
companion object { | ||
@JvmField val EXECUTE = ExplainMode("execute") | ||
|
||
@JvmField val EXPLAIN = ExplainMode("explain") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the entire explain options.
|
||
@JvmField val JSON = OutputFormat("json") | ||
|
||
@JvmField val STRUCT = OutputFormat("struct") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whereas JSON is a large string, Struct is the equivalent proto format that takes advantage of protocol buffers to be much smaller. So Struct is the same as JSON, the same way YAML is the same as JSON. They both offer the same expressiveness, in a slightly different format. There are of course nuances, JSON can contain very large numeric since they are stored as strings. And YAML can contain comments.
This is a remnant from an early discussion. So yes, it should be removed for now.
At some point I hope Firestore will concern itself more with wire format, instead of stuffing JSON into protocol buffers. Which I imagine is like stuffing JSON inside a JSON string (which I believe is the case of REST variant of explain)?
} | ||
} | ||
|
||
class Verbosity private constructor(internal val value: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
} | ||
} | ||
|
||
class Profiles private constructor(internal val value: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
fields.asSequence().map(Field::toProto) | ||
} | ||
|
||
internal class ReplaceStage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
Does it need to be done before release? Maybe (your call)
I only exposed the stage classes when the API required it, not just future proofing raw options. Exposing the stages will require also adding constructors / create methods that offer same semantics and documentation as Pipeline API. I wasn't going to do this work until the dust settled on options, and it is not critical for release in my opinion. There is always the rawStage.
No description provided.