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

fix: preserve the order of the keys #211

Merged
merged 10 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,55 @@ Mongo.insert_many(top, "users", [

## Data Representation

This driver chooses to accept both maps and lists of key-value tuples when encoding BSON documents (1), but will only decode documents into maps. This has the side effect that document field order is lost when decoding. Maps are convenient to work with, but map keys are not ordered, unlike BSON document fields.
This driver chooses to accept both maps and lists of key-value tuples when encoding BSON documents (1), but will only
decode documents into maps. This has the side effect that document field order is lost when decoding.
Maps are convenient to work with, but map keys are not ordered, unlike BSON document fields.

Driver users should represent documents using a list of tuples when field order matters, for example when sorting by multiple fields:

```elixir
Mongo.find(top, "users", %{}, sort: [last_name: 1, first_name: 1, _id: 1])
```

Additionally, the driver accepts both atoms and strings for document keys, but will only decode them into strings. Creating atoms from arbitrary input (such as database documents) is [discouraged](https://elixir-lang.org/getting-started/mix-otp/genserver.html#:~:text=However%2C%20naming%20dynamic,our%20system%20memory!) because atoms are not garbage collected.
Additionally, the driver accepts both atoms and strings for document keys, but will only decode them into strings.
Creating atoms from arbitrary input (such as database documents) is [discouraged](https://elixir-lang.org/getting-started/mix-otp/genserver.html#:~:text=However%2C%20naming%20dynamic,our%20system%20memory!) because atoms are not garbage collected.

## Preserve Order
If the order of the keys are important it is possible to use a different decoder module. The decoder module will
zookzook marked this conversation as resolved.
Show resolved Hide resolved
preserve the order of the keys by adding an attribute `:order` which contains the list of keys in the original order.
If you want to change the `:order` key then define a new decoder module:

```elixir
defmodule MyPreserverOrderDecoder do
@moduledoc false

use BSON.DecoderGenerator, preserve_order: :the_key_order
end
```

and configure the driver to use this new decoder:
```elixir
config :mongodb_driver,
decoder: MyPreserverOrderDecoder

```
The decode module is defined at compiler time. The driver provides two types of decoder:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The decode module is defined at compiler time. The driver provides two types of decoder:
The decoder module is defined at compile time. The driver provides two types of decoder:


```elixir
defmodule BSON.Decoder do
@moduledoc false

use BSON.DecoderGenerator, preserve_order: false
end

defmodule BSON.PreserverOrderDecoder do
zookzook marked this conversation as resolved.
Show resolved Hide resolved
@moduledoc false
Copy link
Contributor

Choose a reason for hiding this comment

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

Would you be willing to post the relevant docs to this module in Hexdocs.pm? I'd volunteer to help write it, since getting docs either on hexdocs or IDE/language server would help discover this feature and decide whether one needs it or not.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yes, of course.


use BSON.DecoderGenerator, preserve_order: :order
end
```

The `BSON.Decoder` is the default decoder.

[BSON symbols (deprecated)](https://bsonspec.org/spec.html#:~:text=Symbol.%20%E2%80%94%20Deprecated) can only be decoded (2).

Expand Down
Loading
Loading