Skip to content
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

Explore default BSON serialization #16

Closed
7 of 12 tasks
AngelMunoz opened this issue Nov 30, 2020 · 2 comments
Closed
7 of 12 tasks

Explore default BSON serialization #16

AngelMunoz opened this issue Nov 30, 2020 · 2 comments
Labels
enhancement New feature or request
Projects

Comments

@AngelMunoz
Copy link
Owner

AngelMunoz commented Nov 30, 2020

There's the possibility that we can just serialize known BSON values in the emitted JSON, as the MongoDB Extended Spec shows, we're kind of doing half work for ObjectIds so instead of just emitting the "objectid" we could be emitting { $oid: "objectid" } in the same way we could be doing the same for int64, dates, etc

Ideally I'd like to use the canonical form when possible, but if there's not an option using the relaxed form should be enough

@AngelMunoz AngelMunoz added the enhancement New feature or request label Nov 30, 2020
@AngelMunoz
Copy link
Owner Author

made some explorations with this and I have the following preview converters

    type ObjectIdConverter() =
        inherit JsonConverter<ObjectId>()

        override _.Read(reader: byref<Utf8JsonReader>, typeToConvert: Type, options: JsonSerializerOptions) =
            ObjectId.Parse(reader.GetString())

        override _.Write(writer: Utf8JsonWriter, value: ObjectId, options: JsonSerializerOptions) =
            writer.WriteStartObject()
            writer.WritePropertyName("$oid")
            writer.WriteStringValue(value.ToString())
            writer.WriteEndObject()

    type DateTimeConverter() =
        inherit JsonConverter<DateTime>()

        override _.Read(reader: byref<Utf8JsonReader>, typeToConvert: Type, options: JsonSerializerOptions) =
            let deserialized =
                JsonSerializer.Deserialize<{| ``$date``: {| ``$numberLong``: string |} |}>(reader.GetString())

            DateTimeOffset
                .FromUnixTimeMilliseconds(deserialized.``$date``.``$numberLong`` |> int64)
                .Date

        override _.Write(writer: Utf8JsonWriter, value: DateTime, options: JsonSerializerOptions) =
            let stringValue =
                DateTimeOffset
                    .op_Implicit(value)
                    .ToUnixTimeMilliseconds()
                |> string

            writer.WriteStartObject()
            writer.WritePropertyName("$date")
            writer.WriteStartObject()
            writer.WritePropertyName("$numberLong")
            writer.WriteStringValue(stringValue)
            writer.WriteEndObject()
            writer.WriteEndObject()

they are producing the following json

{
    "insert":"users",
    "documents":[
        {
            "_id":{
                "$oid":"5fc5b6e4545a4775f7f9bfda"
            },
            "age":29,
            "name":"Peter"
        },
        {
            "_id":{
                "$oid":"5fc5b6e4545a4775f7f9bfdb"
            },
            "age":20,
            "name":"Sandra"
        },
        {
            "age":35,
            "name":"Mike"
        },
        {
            "age":39,
            "name":"Perla"
        },
        {
            "age":1,
            "name":"Updateme"
        },
        {
            "age":50,
            "name":"Deleteme"
        }
    ]
}
{
    "update":"users",
    "updates":[
        {
            "q":{
                "name":"Updateme"
            },
            "u":{
                "age":5,
                "name":"Updated",
                "updatedAt":{
                    "$date":{
                        "$numberLong":"1606792932488"
                    }
                }
            },
            "upsert":false,
            "multi":false
        }
    ]
}

NoSQL booster reads the values and shows them as their intended serialized values
image

it also allows things like these

find "users" {
        // equivalent to a mongo query filter 
        // { age: { $gt: 10} }
        filter {| updatedAt = {| ``$ne`` = DateTime.Now |} |}
    }
{
    "find":"users",
    "filter":{
        "updatedAt":{
            "$ne":{
                "$date":{
                    "$numberLong":"1606793830175"
                }
            }
        }
    }
}

and seem to work fine
image
of course there might be some caveats to how to do a propper search but that's out of the scope of this project

@AngelMunoz AngelMunoz added this to In progress in Development Nov 30, 2020
@AngelMunoz
Copy link
Owner Author

I'm not sure how worth or what are the correct data types in .NET for those so I'll leave them pending, If anyone ever wants them, they are very easy to implement

@AngelMunoz AngelMunoz moved this from In progress to Done in Development Dec 3, 2020
AngelMunoz added a commit that referenced this issue Dec 7, 2020
these caveats have been addressed by  #16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Development

No branches or pull requests

1 participant