# .explain() result in ParseSwift

**URL:** <https://community.parseplatform.org/t/explain-result-in-parseswift/1557>\
**Category:** ParseSwift SDK\
**Tags:** query\
**Created:** [April 10, 2021, 5:51pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557 "2021-04-10T17:51:29Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![lsmilek1](https://community.parseplatform.org/user_avatar/community.parseplatform.org/lsmilek1/32/629_2.png) [@lsmilek1](https://community.parseplatform.org/u/lsmilek1)\
**Post date:** [April 10, 2021, 5:51pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/1 "2021-04-10T17:51:29Z")

</div>

Hi,

I would like to investigate query performance and was able to set a simple function that returns array of objects.

```
Parse.Cloud.define("newProfiles", async (request) => {
    const basicQuery = new Parse.Query("PrsProfile");
    basicQuery.lessThanOrEqualTo("ag", 26);
    basicQuery.greaterThanOrEqualTo("ag", 23);
    const results = await basicQuery.find({ sessionToken: request.user.getSessionToken() });
    return results;
  });

```

This works as intended and I have PrsProfile object already as a struct, so decoding is not an issue. But when I chain `basicQuery.explain()` in to the function, it returns result that I can’t read well:

> error: The data couldn’t be read because it isn’t in the correct format. Format: Optional("{\"result\":{\"queryPlanner\":{\"mongosPlannerVersion\":1,\"winningPlan\":{\"stage\":\"SINGLE\_SHARD\",\"shards\":[{\"shardName\":\"rs6\",\"connectionString\":\"rs6/MongoRS601A.back4app.com:27018,[MongoRS602A.back4app.com:27018](http://MongoRS602A.back4app.com:27018)\",\"serverInfo\":{\"host\":\"MongoRS601A.back4app.com\",\"port\":27018,\"version\":\"3.6.8-2.0\",\"gitVersion\":\"1fb3fbd45602ef799b4053edbe1f2748ab97eebe\"},\"plannerVersion\":1,\"namespace\":\"a1b5c903c7814f7a836a269dc63ff84f.PrsProfile\",\"indexFilterSet\":false,\"parsedQuery\":{\"$and\":[{\"ag\":{\"$lte\":26}},{\"ag\":{\"$gte\":23}},{\"\_rperm\":{\"$in\":[null,\"_\",\"zyLHKLV5Ll\"]}}]},\"winningPlan\":{\"stage\":\"LIMIT\",\"limitAmount\":100,\"inputStage\":{\"stage\":\"COLLSCAN\",\"filter\":{\"$and\":[{\"ag\":{\"$lte\":26}},{\"ag\":{\"$gte\":23}},{\"\_rperm\":{\"$in\":[null,\"_\",\"zyLHKLV5Ll\"]}}]},\"direction\":\"forward\"}},\"rejectedPlans\":}]}},\"executionStats\":{\"nReturned\":1,\"executionTimeMillis\":3,\"totalKeysExamined\":0,\"totalDocsExamined\":1,\"executionStages\":{\"stage\":\"SINGLE\_SHARD\",\"nReturned\":1,\"executionTimeMillis\":3,\"totalKeysExamined\":0,\"totalDocsExamined\":1,\"totalChildMillis\":0,\"shards\":[{\"shardName\":\"rs6\",\"executionSuccess\":true,\"executionStages\":{\"stage\":\"LIMIT\",\"nReturned\":1,\"executionTimeMillisEstimate\":0,\"works\":3,\"advanced\":1,\"needTime\":1,\"needYield\":0,\"saveState\":0,\"restoreState\":0,\"isEOF\":1,\"invalidates\":0,\"limitAmount\":100,\"inputStage\":{\"stage\":\"COLLSCAN\",\"filter\":{\"$and\":[{\"ag\":{\"$lte\":26}},{\"ag\":{\"$gte\":23}},{\"\_rperm\":{\"$in\":[null,\"\*\",\"zyLHKLV5Ll\"]}}]},\"nReturned\":1,\"executionTimeMillisEstimate\":0,\"works\":3,\"advanced\":1,\"needTime\":1,\"needYield\":0,\"saveState\":0,\"restoreState\":0,\"isEOF\":1,\"invalidates\":0,\"direction\":\"forward\",\"docsExamined\":1}}}]},\"allPlansExecution\":[{\"shardName\":\"rs6\",\"allPlans\":}]},\"ok\":1}}")")

I am using following definition with ParseSwift SDK:

```
let findQuery = Cloud(functionJobName: "newProfiles")
        findQuery.runFunction { result in
            switch result {
            case .success(let results):
                print("Response from cloud function: \(results))")
            case .failure(let error):
                print("Error calling cloud function: \(error)")
            }
        }

```

The typealias in the Cloud struct is for me the unknown…

```
import** ParseSwift

//: Create your own value typed `ParseCloud` type.
struct** Cloud: ParseCloud {

//: Return type of your Cloud Function
typealias ReturnType = ????

//: These are required for Object
var functionJobName: String

}

```

Does anyone has a wrapper or useful trick, how to print explain() result in Xcode in a better way?

Thank you!

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 10, 2021, 9:28pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/2 "2021-04-10T21:28:58Z")

</div>

Swift is strongly typed so you need to know the type you are returning. Since you’re calling explain from cloud code, you should know what it’s returning. Note that queries in ParseSwift are able to be `explained` as well:

> <https://github.com/parse-community/Parse-Swift/blob/1d3d1d671f6e67edcdd6abcc540e23d35e42b438/ParseSwift.playground/Pages/7%20-%20GeoPoint.xcplaygroundpage/Contents.swift#L177-L189>

The simple solution is to use `AnyDecodable ` (like the playground example above), in the your particular case:

```auto
struct ExplainType: Decodable {
  let result: AnyDecodable
}

struct Cloud: ParseCloud {

//: Return type of your Cloud Function
typealias ReturnType = ExplainType

//: These are required for Object
var functionJobName: String

}

```

This is replicating the `AnyResultResponse` type:

> <https://github.com/parse-community/Parse-Swift/blob/702422287d84c765d6366f9543dbdc4730ff7d8b/Sources/ParseSwift/API/Responses.swift#L109-L112>

You can see all of the generic return types ParseSwift uses in the file above.

Once you have `AnyDecodable `, you can cast the value to what you expect. I don’t use mongo, so I don’t know the types its explain returns, but you can look at the results you posted. You can try below to get through the first layer:

```auto
findQuery.runFunction { result in
            switch result {
            case .success(let results):
                print("Response from cloud function: \(results.result))")
                //If you know the type, use that instead of Any. If Any doesn't work use AnyDecodable again
                guard let explainDictionary = results.result.value as? [String: Any] else {
                        return
                 }
                print("Casted explain: \(explainDictionary)"
            case .failure(let error):
                print("Error calling cloud function: \(error)")
            }
        }

```

---

<div class="post-metadata">

**Author:** ![lsmilek1](https://community.parseplatform.org/user_avatar/community.parseplatform.org/lsmilek1/32/629_2.png) [@lsmilek1](https://community.parseplatform.org/u/lsmilek1)\
**Post date:** [April 11, 2021, 9:01am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/3 "2021-04-11T09:01:28Z")

</div>

Hi Corey,

thank you for your response! I was able to decode the response from cloud function as you mentioned by defining the return type as `AnyDecodable` in the Cloud struct:

```
func fetchUserViaCloudCode() {
        let findQuery = Cloud(functionJobName: "newProfiles")
        findQuery.runFunction { result in
            switch result {
            case .success(let results):
                guard let explainDictionary = results.value as? [String: Any] else {
                    return
                }
                let executionStats = explainDictionary["executionStats"] as? [String: Any]
                for key in executionStats!.keys {
                    switch key {
                    case "totalKeysExamined", "totalDocsExamined", "nReturned", "executionTimeMillis": print("-> \(key) \(executionStats![key]!)")
                    default: ()
                    }
                    
                }
            case .failure(let error):
                print("Error calling cloud function: \(error)")
            }
        }
    }

```

unfortunately, when I follow your playgrounds example and try to cast the result of a “find” function as AnyDecodable it does not work and it catches error decoding due to format:

```
finalQuery.find(explain: true) { (result: Result<[AnyDecodable], ParseError>) in
            switch result {
            case .success(let results):
                guard let explainDictionary = results.first?.value as? [String: Any] else {
                    return
                }
                let executionStats = explainDictionary["executionStats"] as? [String: Any]
                for key in executionStats!.keys {
                    switch key {
                    case "totalKeysExamined", "totalDocsExamined", "nReturned", "executionTimeMillis": print("-> \(key) \(executionStats![key]!)")
                    default: ()
                    }

                }
            case .failure(let error):
                print("Error calling cloud function: \(error)")
            }
        }

```

If I try to set it as no array result I get an compiler error as he expects array

```
finalQuery.find(explain: **true** ) { (result: Result<AnyDecodable, ParseError>) **in**

```

I apologise if I missed any basic swift declaration login, I am still an beginner in a programming world.

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 11:26am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/4 "2021-04-11T11:26:05Z")

</div>

Can you post the full error?

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 2:12pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/6 "2021-04-11T14:12:50Z")

</div>

My guess is this is a bug on parse-server and not Parse-Swift and someone on the server team should probably pick up the Q&A here…

I say this because it doesn’t appear when using explain in Postgres. When I added `explain` to the Postgres adapter on the parse-server ([PR 6506](https://github.com/parse-community/parse-server/pull/6506)), I made sure it’s always returned in JSON format so it can always be decoded:

> <https://github.com/parse-community/parse-server/blob/45d00cee60d0b273591b5ee6ebe7c9b610fae26e/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js#L827-L833>

~~Looking at the `explain` results you’ve shown along with some of my own testing, the Mongo version of explain isn’t always returning a JSON version of `explain`. CloudCode and the JS SDK most likely show results fine in because JS isn’t a strongly typed language and isn’t trying to decode JSON to specific types. Conversely, Swift is, and expects everything from the server to be in a “correct” JSON format or else it throws errors. The mongo version of `explain` doesn’t appear to be in a correct JSON format.~~

Update: the problem is a mongo `explain` isn’t being returned within a JSON array.

If what I said above is true (the server team will need to confirm), there will most likely need to be a fix in this file [parse-server/MongoStorageAdapter.js at master · parse-community/parse-server · GitHub](https://github.com/parse-community/parse-server/blob/master/src/Adapters/Storage/Mongo/MongoStorageAdapter.js). I found some info about explain in mongo (but I don’t use it, so I won’t be able to provide any additional insight beyond this): [explain — MongoDB Manual](https://docs.mongodb.com/manual/reference/command/explain/)

A workaround could be to use your Cloud Code explain function and only return the fields your care about to Parse-Swift.

---

<div class="post-metadata">

**Author:** ![lsmilek1](https://community.parseplatform.org/user_avatar/community.parseplatform.org/lsmilek1/32/629_2.png) [@lsmilek1](https://community.parseplatform.org/u/lsmilek1)\
**Post date:** [April 11, 2021, 2:18pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/7 "2021-04-11T14:18:14Z")

</div>

Thank you for a great support, Corey! As I will move this query function in the cloud code at the end anyway, I am continuing with the cloud code explain.

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 2:26pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/8 "2021-04-11T14:26:59Z")

</div>

Posting additional results (using a simple geo query) for the server team. An additional question would be is `explain` executing or the command here (it looks like it might be, but I’m unsure). I would think the default would be not to execute the query/command:

`error: The data couldn’t be read because it isn’t in the correct format. Format: Optional(\"{\\\"results\\\":{\\\"queryPlanner\\\":{\\\"plannerVersion\\\":1,\\\"namespace\\\":\\\"parse_hipaa.GameScore\\\",\\\"indexFilterSet\\\":false,\\\"parsedQuery\\\":{\\\"$and\\\":[{\\\"score\\\":{\\\"$gt\\\":9}},{\\\"_rperm\\\":{\\\"$in\\\":[null,\\\"*\\\"]}},{\\\"location\\\":{\\\"$nearSphere\\\":[-30,40]}}]},\\\"winningPlan\\\":{\\\"stage\\\":\\\"LIMIT\\\",\\\"limitAmount\\\":1,\\\"inputStage\\\":{\\\"stage\\\":\\\"FETCH\\\",\\\"filter\\\":{\\\"$and\\\":[{\\\"_rperm\\\":{\\\"$in\\\":[null,\\\"*\\\"]}},{\\\"score\\\":{\\\"$gt\\\":9}}]},\\\"inputStage\\\":{\\\"stage\\\":\\\"GEO_NEAR_2D\\\",\\\"keyPattern\\\":{\\\"location\\\":\\\"2d\\\"},\\\"indexName\\\":\\\"location_2d\\\",\\\"indexVersion\\\":2,\\\"inputStage\\\":{\\\"stage\\\":\\\"FETCH\\\",\\\"inputStage\\\":{\\\"stage\\\":\\\"IXSCAN\\\",\\\"keyPattern\\\":{\\\"location\\\":\\\"2d\\\"},\\\"indexName\\\":\\\"location_2d\\\",\\\"isMultiKey\\\":false,\\\"isUnique\\\":false,\\\"isSparse\\\":false,\\\"isPartial\\\":false,\\\"indexVersion\\\":2,\\\"direction\\\":\\\"forward\\\",\\\"indexBounds\\\":{\\\"location\\\":[\\\"[BinData(128, 69D89D89D8380000), BinData(128, 69D89D89D83BFFFF)]\\\",\\\"[BinData(128, 69D89D89D83C0000), BinData(128, 69D89D89D83FFFFF)]\\\",\\\"[BinData(128, 69D89D89D86A0000), BinData(128, 69D89D89D86AFFFF)]\\\",\\\"[BinData(128, 69D89D89D86B8000), BinData(128, 69D89D89D86BBFFF)]\\\",\\\"[BinData(128, 69D89D89D8870000), BinData(128, 69D89D89D887FFFF)]\\\",\\\"[BinData(128, 69D89D89D88C0000), BinData(128, 69D89D89D88FFFFF)]\\\",\\\"[BinData(128, 69D89D89D8900000), BinData(128, 69D89D89D89FFFFF)]\\\",\\\"[BinData(128, 69D89D89D8A55000), BinData(128, 69D89D89D8A55FFF)]\\\",\\\"[BinData(128, 69D89D89D8B00000), BinData(128, 69D89D89D8B3FFFF)]\\\",\\\"[BinData(128, 69D89D89D8B40000), BinData(128, 69D89D89D8B7FFFF)]\\\",\\\"[BinData(128, 69D89D89D8BC0000), BinData(128, 69D89D89D8BCFFFF)]\\\",\\\"[BinData(128, 69D89D89D8BD0000), BinData(128, 69D89D89D8BDFFFF)]\\\",\\\"[BinData(128, 69D89D89D8C00000), BinData(128, 69D89D89D8CFFFFF)]\\\",\\\"[BinData(128, 69D89D89D8E00000), BinData(128, 69D89D89D8E3FFFF)]\\\",\\\"[BinData(128, 69D89D89D8E40000), BinData(128, 69D89D89D8E4FFFF)]\\\",\\\"[BinData(128, 69D89D89D8E80000), BinData(128, 69D89D89D8E80FFF)]\\\"]}}}}}},\\\"rejectedPlans\\\":[]},\\\"executionStats\\\":{\\\"executionSuccess\\\":true,\\\"nReturned\\\":1,\\\"executionTimeMillis\\\":0,\\\"totalKeysExamined\\\":1,\\\"totalDocsExamined\\\":2,\\\"executionStages\\\":{\\\"stage\\\":\\\"LIMIT\\\",\\\"nReturned\\\":1,\\\"executionTimeMillisEstimate\\\":0,\\\"works\\\":5,\\\"advanced\\\":1,\\\"needTime\\\":3,\\\"needYield\\\":0,\\\"saveState\\\":0,\\\"restoreState\\\":0,\\\"isEOF\\\":1,\\\"limitAmount\\\":1,\\\"inputStage\\\":{\\\"stage\\\":\\\"FETCH\\\",\\\"filter\\\":{\\\"$and\\\":[{\\\"_rperm\\\":{\\\"$in\\\":[null,\\\"*\\\"]}},{\\\"score\\\":{\\\"$gt\\\":9}}]},\\\"nReturned\\\":1,\\\"executionTimeMillisEstimate\\\":0,\\\"works\\\":4,\\\"advanced\\\":1,\\\"needTime\\\":3,\\\"needYield\\\":0,\\\"saveState\\\":0,\\\"restoreState\\\":0,\\\"isEOF\\\":0,\\\"docsExamined\\\":1,\\\"alreadyHasObj\\\":1,\\\"inputStage\\\":{\\\"stage\\\":\\\"GEO_NEAR_2D\\\",\\\"nReturned\\\":1,\\\"executionTimeMillisEstimate\\\":0,\\\"works\\\":4,\\\"advanced\\\":1,\\\"needTime\\\":3,\\\"needYield\\\":0,\\\"saveState\\\":0,\\\"restoreState\\\":0,\\\"isEOF\\\":0,\\\"keyPattern\\\":{\\\"location\\\":\\\"2d\\\"},\\\"indexName\\\":\\\"location_2d\\\",\\\"indexVersion\\\":2,\\\"searchIntervals\\\":[{\\\"minDistance\\\":0,\\\"maxDistance\\\":3.5829649157275663,\\\"maxInclusive\\\":false,\\\"nBuffered\\\":1,\\\"nReturned\\\":1}],\\\"inputStage\\\":{\\\"stage\\\":\\\"FETCH\\\",\\\"nReturned\\\":1,\\\"executionTimeMillisEstimate\\\":0,\\\"works\\\":2,\\\"advanced\\\":1,\\\"needTime\\\":0,\\\"needYield\\\":0,\\\"saveState\\\":0,\\\"restoreState\\\":0,\\\"isEOF\\\":1,\\\"docsExamined\\\":1,\\\"alreadyHasObj\\\":0,\\\"inputStage\\\":{\\\"stage\\\":\\\"IXSCAN\\\",\\\"nReturned\\\":1,\\\"executionTimeMillisEstimate\\\":0,\\\"works\\\":2,\\\"advanced\\\":1,\\\"needTime\\\":0,\\\"needYield\\\":0,\\\"saveState\\\":0,\\\"restoreState\\\":0,\\\"isEOF\\\":1,\\\"keyPattern\\\":{\\\"location\\\":\\\"2d\\\"},\\\"indexName\\\":\\\"location_2d\\\",\\\"isMultiKey\\\":false,\\\"isUnique\\\":false,\\\"isSparse\\\":false,\\\"isPartial\\\":false,\\\"indexVersion\\\":2,\\\"direction\\\":\\\"forward\\\",\\\"indexBounds\\\":{\\\"location\\\":[\\\"[BinData(128, 69D89D89D8380000), BinData(128, 69D89D89D83BFFFF)]\\\",\\\"[BinData(128, 69D89D89D83C0000), BinData(128, 69D89D89D83FFFFF)]\\\",\\\"[BinData(128, 69D89D89D86A0000), BinData(128, 69D89D89D86AFFFF)]\\\",\\\"[BinData(128, 69D89D89D86B8000), BinData(128, 69D89D89D86BBFFF)]\\\",\\\"[BinData(128, 69D89D89D8870000), BinData(128, 69D89D89D887FFFF)]\\\",\\\"[BinData(128, 69D89D89D88C0000), BinData(128, 69D89D89D88FFFFF)]\\\",\\\"[BinData(128, 69D89D89D8900000), BinData(128, 69D89D89D89FFFFF)]\\\",\\\"[BinData(128, 69D89D89D8A55000), BinData(128, 69D89D89D8A55FFF)]\\\",\\\"[BinData(128, 69D89D89D8B00000), BinData(128, 69D89D89D8B3FFFF)]\\\",\\\"[BinData(128, 69D89D89D8B40000), BinData(128, 69D89D89D8B7FFFF)]\\\",\\\"[BinData(128, 69D89D89D8BC0000), BinData(128, 69D89D89D8BCFFFF)]\\\",\\\"[BinData(128, 69D89D89D8BD0000), BinData(128, 69D89D89D8BDFFFF)]\\\",\\\"[BinData(128, 69D89D89D8C00000), BinData(128, 69D89D89D8CFFFFF)]\\\",\\\"[BinData(128, 69D89D89D8E00000), BinData(128, 69D89D89D8E3FFFF)]\\\",\\\"[BinData(128, 69D89D89D8E40000), BinData(128, 69D89D89D8E4FFFF)]\\\",\\\"[BinData(128, 69D89D89D8E80000), BinData(128, 69D89D89D8E80FFF)]\\\"]},\\\"keysExamined\\\":1,\\\"seeks\\\":1,\\\"dupsTested\\\":0,\\\"dupsDropped\\\":0}}}}},\\\"allPlansExecution\\\":[]},\\\"serverInfo\\\":{\\\"host\\\":\\\"33fdd198c5e7\\\",\\\"port\\\":27017,\\\"version\\\":\\\"4.4.4-6\\\",\\\"gitVersion\\\":\\\"f3dd4bc7c7500705a537de40bb4d6127ba498bd3\\\"},\\\"ok\\\":1}}\")`

I don’t believe some of the fields above can be decoded properly in JSON, but I could be wrong.

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 3:47pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/9 "2021-04-11T15:47:09Z")

</div>

@dplewis @davimacedo @dblythy @Manuel it looks like there’s a bug on the server with the mongo version of `explain` (you can ignore my JSON comments above as the fix below is the appropriate one). The problem is the results of a mongo explain are:

```auto
internal struct AnyResultsResponse<U: Decodable>: Decodable {
    let results: U //Technically, when using results (plural), it should be an array
    //let results: [U] This is what it should be
}

```

The solution would be to wrap the result of a mongo explain within an array. The return types of first, find, count, etc. in a regular query always returns `results: [U]`, but the Mongo explain isn’t following this pattern. If you look at the postgres PR I linked in [this comment](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/6), it does it correctly.

@lsmilek1 if you want, you can take my comments here and open an issue on the parse-server GitHub repo. You can ignore my JSON comments.

---

<div class="post-metadata">

**Author:** ![Manuel](https://community.parseplatform.org/user_avatar/community.parseplatform.org/manuel/32/186_2.png) [@Manuel](https://community.parseplatform.org/u/Manuel)\
**Post date:** [April 11, 2021, 4:11pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/10 "2021-04-11T16:11:20Z")

</div>

So the JSON parsing server side of the explain response from MongoDB is faulty?

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 4:19pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/11 "2021-04-11T16:19:07Z")

</div>

Not the JSON, I was wrong about that.

The part that’s faulty is the result of a mongo explain needs to be added into an array to fit the pattern of a query return type. It’s currently being sent as a single element.

The fix is probably a one-liner. Me skimming the mongo adapter, the problem is probably the line below:

> <https://github.com/parse-community/parse-server/blob/45d00cee60d0b273591b5ee6ebe7c9b610fae26e/src/Adapters/Storage/Mongo/MongoStorageAdapter.js#L625>

My guess is `objects` from a mongo explain isn’t array, but was assumed to be, so it needs to be added to an array. I believe I ran into this problem when I added the postgres explain but caught it when I was writing the testcases.

---

<div class="post-metadata">

**Author:** ![Manuel](https://community.parseplatform.org/user_avatar/community.parseplatform.org/manuel/32/186_2.png) [@Manuel](https://community.parseplatform.org/u/Manuel)\
**Post date:** [April 11, 2021, 4:53pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/12 "2021-04-11T16:53:17Z")

</div>

Got it, that seems like an easy fix, although a breaking change for developers who parse the current output, right?

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 11, 2021, 5:27pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/13 "2021-04-11T17:27:49Z")

</div>

Yup, will definitely be a breaking change for those who use it.

It will probably also break some of the mongo explain testcases, but the fix in those should be to take the first element of the array before parsing

---

<div class="post-metadata">

**Author:** ![Manuel](https://community.parseplatform.org/user_avatar/community.parseplatform.org/manuel/32/186_2.png) [@Manuel](https://community.parseplatform.org/u/Manuel)\
**Post date:** [April 12, 2021, 1:52am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/14 "2021-04-12T01:52:18Z")

</div>

It is actually possible that this only affects certain MongoDB versions.

I made a PR to adapt the `hint` tests to work with MongoDB 4.4 because I think the DB response changed, see [spec/ParseQuery.hint.spec.js](https://github.com/parse-community/parse-server/pull/7161/files).

Maybe we only need to adapt the response for MongoDB \>= 4.4, but haven’t looked into it.

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 12, 2021, 2:18am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/15 "2021-04-12T02:18:58Z")

</div>

It was giving me an error on 4.2 also, but I didn’t verify if it was the same problem. ~~I will check soon~~. I only checked 4.4 and 4.2

Update: Verified it’s the same problem on 4.2

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [April 12, 2021, 2:51am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/16 "2021-04-12T02:51:34Z")

</div>

Also, the original error reported here: [.explain() result in ParseSwift](https://community.parseplatform.org/t/explain-result-in-parseswift/1557) shows mongo version 3.6.8-2.0

---

<div class="post-metadata">

**Author:** ![Manuel](https://community.parseplatform.org/user_avatar/community.parseplatform.org/manuel/32/186_2.png) [@Manuel](https://community.parseplatform.org/u/Manuel)\
**Post date:** [April 12, 2021, 2:54am UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/17 "2021-04-12T02:54:20Z")

</div>

Thanks, well investigated!

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [June 20, 2021, 11:17pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/18 "2021-06-20T23:17:28Z")

</div>

I’ve opened a PR to fix this issue:

> <https://github.com/parse-community/parse-server/pull/7440>
>
> \### New Pull Request Checklist
> \<!--
> Please check the following boxes \[x\] b…efore submitting your issue.
> Click the "Preview" tab for better readability.
> Thanks for contributing to Parse Server!
> \--\>
> 
> \- \[x\] I am not disclosing a \[vulnerability\](https://github.com/parse-community/parse-server/blob/master/SECURITY.md).
> \- \[x\] I am creating this PR in reference to #7442.
> 
> \### Issue Description
> 
> 
> \`explain\` for mongo is currently returning an \`object\` when returning results. This conflicts with trying to decode explain results because it should return an array of objects when using \`find\` 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\](https://community.parseplatform.org/t/explain-result-in-parseswift/1557)
> 
> 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
> \<!--
> Add TODOs that need to be completed before merging this PR.
> Delete suggested TODOs that do not apply to this PR.
> \--\>
> 
> \- \[x\] Fix current test cases that were adapted to bug
> \- \[x\] Add entry to changelog

---

<div class="post-metadata">

**Author:** ![cbaker6](https://community.parseplatform.org/user_avatar/community.parseplatform.org/cbaker6/32/114_2.png) [@cbaker6](https://community.parseplatform.org/u/cbaker6)\
**Post date:** [January 8, 2022, 5:20pm UTC](https://community.parseplatform.org/t/explain-result-in-parseswift/1557/19 "2022-01-08T17:20:53Z")

</div>

The Swift SDK 3.1.0 can now explain Mongo queries. See the PR for details:

> <https://github.com/parse-community/Parse-Swift/pull/314>
>
> \### New Pull Request Checklist
> \<!--
> Please check the following boxes \[x\] b…efore submitting your issue.
> Click the "Preview" tab for better readability.
> Thanks for contributing to Parse Platform!
> \--\>
> 
> \- \[x\] I am not disclosing a \[vulnerability\](https://github.com/parse-community/Parse-Swift/security/policy).
> \- \[x\] I am creating this PR in reference to an \[issue\](https://github.com/parse-community/Parse-Swift/issues?q=is%3Aissue).
> 
> \### Issue Description
> 
> The Swift SDK can't explain MongoDB queries due to a bug on the server-side response. PR https://github.com/parse-community/parse-server/issues/7440 was created on the server, but the server team has chosen not to fix the code.
> 
> Originally discussed in: https://community.parseplatform.org/t/explain-result-in-parseswift/1557
> 
> Related issue: #N/A https://github.com/parse-community/parse-server/issues/7442
> 
> \### Approach
> 
> Add a new internal response type that doesn't expect \`results\` to be an array. When the user wants to explain a mongo query, they set the flag, \`isUsingMongoDB=true\`. This allows the mongo explained queries to use the same methods as the ones already in the SDK.
> 
> \### TODOs before merging
> \<!--
> Add TODOs that need to be completed before merging this PR.
> Delete TODOs that do not apply to this PR.
> \--\>
> 
> \- \[x\] Add tests
> \- \[x\] Add entry to changelog
> \- \[x\] Add changes to documentation (guides, repository pages, in-code descriptions)
