-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
fix: mongo explain queries should always return as an array of results #7440
Conversation
Codecov Report
@@ Coverage Diff @@
## alpha #7440 +/- ##
==========================================
- Coverage 93.93% 93.90% -0.03%
==========================================
Files 181 181
Lines 13267 13267
==========================================
- Hits 12462 12459 -3
- Misses 805 808 +3
Continue to review full report at Codecov.
|
I'll submit the JS fix later today as that will be needed for the test cases. Essentially, an explainable first is needed. |
@@ -622,7 +622,7 @@ export class MongoStorageAdapter implements StorageAdapter { | |||
) | |||
.then(objects => { | |||
if (explain) { | |||
return objects; | |||
return [objects]; |
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.
Just to understand, will this array ever have more than one item?
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 will let @cbaker6 answer this, but to throw in my observation:
Although MongoDB has changed the structure of the explain output in the past, they did not change the root which is a dictionary with key queryPlanner
. Also see https://docs.mongodb.com/manual/reference/explain-results/
The more likely reason this result array could contain more than 1 item is if we have a use case in Parse Server in the future where we may want to return more than 1 item.
I tend to think that this is a symptom of a conceptual flaw in our explain
implementation. The underlying issue is that explain
does not return the same type as find
. That means that an explain
operation should not be executed with find
and explain
as an option. It should be a distinct command which returns a distinct type, which is object.
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.
Just to understand, will this array ever have more than one item?
@davimacedo Not to my knowledge, but I think it can be possible in the future. @mtrezza’s explanation works here:
I tend to think that this is a symptom of a conceptual flaw in our explain implementation. The underlying issue is that explain does not return the same type as find.
This causes an issue for strongly typed languages because find on the parse server is expected to always return an array, not a single object. Currently, there is no way to run explain in the Swift SDK when using Mongo because of this flaw. A dev will have to run an afterFind trigger in Cloud Code and modify the results for it work. This isn’t the case for the Postgres implementation because it follows the rules of find.
That means that an explain operation should not be executed with find and explain as an option. It should be a distinct command which returns a distinct type, which is object.
@mtrezza comment about is a possible solution, but this will cause for additional complicated code on the server and Client SDKs (currently JS and Swift, none of the others seem to have this implemented). I recommend just making Mongo explain follow the rules of find (this PR) so explain can be used as an option in a find/first query.
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.
Also see https://docs.mongodb.com/manual/reference/explain-results/ The more likely reason this result array could contain more than 1 item is if we have a use case in Parse Server in the future where we may want to return more than 1 item.
@mtrezza’s comment above also is reasonable. I didn’t include it because it’s separate from the Mongo Adapter not following the current rules of find, but is still a plus when moving in direction of accepting this PR
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’ll note, a few of the fixes I’ve added to the server have been due to:
- Bringing the SDK (Swift) that uses a strongly typed language up to parity with the server features.
- Using a strict JSON encoder/decoder (ParseEncoder/JSONDecoder in the Swift SDK)
Since the JS SDK seems to be the only other client SDK that seems to be at feature parity (the Flutter SDK has more features than the others but doesn’t seem to have adequate testcases from what I can find, so I don’t count it), it causes some mistakes because both JS don’t rely on the 2 items I listed above.
To be fair, I think all of the features added without testing against the 2 items above have been implemented well. There’s just some minor bugs in which I submitted PRs for, this Mongo explain PR being one of them.
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.
The "bug fix" is a breaking change. Moving to return an object is another breaking change. So why not break only 1 time in a way that is sustainable?
The bug fix will only break the explain portion of SDKs that use explain (I don't believe there are many, maybe just JS from what I can find), Swift will work. The feature add of 7637 will break query's in general across all SDKs. I don't place these types of breaks in the same category. Plus, one is finished while the other seems to be in a conceptual phase from what I can see.
Also, if I understand correctly, this is currently a "bug" only from the standpoint of the Swift SDK, not for any other SDK, is that correct?
I think you are asking if the Swift SDK the only SDK that doesn't conform to a known bug. The answer here is, "yes" I don't program anything to conform to bugs I know about. I consider bugs to be things coded on accidents or unintentional, not coded on purpose.
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.
Currently, mongo's explain
returns an object
, Postgres returns an array of objects
. Even in 7637, you are going to have to make a design decision with Mongo because of strongly typed languages; explain: [object]
or explain: object
. If it's the former, then it's an adjustment of this PR, which makes it closer to an incremental change. If you modify Postgres, you will have to pull the first item out of the array to make the explain property work as explain: object
. IMO, an array of objects gives you the most flexibility...
Postgres reference (Look in Example
section, FORMAT JSON
): https://www.postgresql.org/docs/current/sql-explain.html
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.
A breaking change won't be introduced until 2023. If we change to retuning an object instead of an array in 2022, any other "intermediary" effort (i.e. returning an array for explain
) will be practically unreleased.
To evaluate any intermediary steps, we would have to be know where we ultimately want to go. I'm starting to repeat myself, but in my opinion, the sustainable way forward is to return something like:
{
results: [...],
meta: {
cursor: ...,
explain: ...
}
}
Because how else would we return results and meta data? Do we agree on that?
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.
The way you have the meta data looks good, just need to decide if cursor and explain will be an array of objects or an object.
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.
They will be objects for the same reason as we want to return an object on the root level: We cannot know how the results of explain
or cursor
may change in the future. Once we use an array, we are confining the subsequent structure to be items in a list. We only want to do that if we have a strong reason to assume that we will always expect a list of items, such as results
, which will likely always be a list of objects.
Object and array can of course be used interchangeably, but if we use an array, we'd have to remember what information we expect at which index. And the problems begin when a response is supposed to not contain any value on an intermediary index. In that sense, we want to push the use of arrays as far out as possible and necessary in the response structure.
|
Concerted to draft:
|
Thanks for opening this pull request!
|
New Pull Request Checklist
Issue Description
explain
for mongo is currently returning anobject
when returning results. This conflicts with trying to decode explain results because it should return an array of objects when usingfind
instead of a single object.This error was probably not seen before because JS and some other languages are "not strongly typed," meaning the language doesn't care if a single object is returned instead of an array of objects. This is not the case with the Swift SDK.
This also requires a fix to the JS SDK for proper support along with any other SDK that adapted to the bug.
This will be a breaking change as devs who use mongo probably programmed to the bug mentioned above. Close #7442
Originally discussed on community.parseplatform.org
Related issue: #7442
Approach
Make find in the MongoStorageAdapter return an array of objects to conform to the way it's suppose to return results.
TODOs before merging