mongo_orm Exception: missing bson key: publish_acl (Exception)
When you extend your field definitions in the mongo_orm document classes, specifically with embedded documents, you might run into the following runtime (!) error:
Exception: missing bson key: <name> (Exception)
This is not an error in your code – your code is raising, because the database structure is not as it expects it to be!
Here’s the sample code which I am using for creating a Mongo Auth & ACL DB for VerneMQ:
class PublishACL < Mongo::ORM::EmbeddedDocument
field pattern : String
field max_qos : Int32
field allowed_retain : Bool
field max_payload_size : Int32
endclass SubscribeACL < Mongo::ORM::EmbeddedDocument
field pattern : String
field max_qos : Int32
endclass MQTTCredentials < Mongo::ORM::Document
collection_name “vmq_acl_auth”
field mountpoint : String
field client_id : String
field username : String
field passhash : String
embeds_many :publish_acl, class_name: Papi::PublishACL
embeds_many :subscribe_acl, class_name: Papi::SubscribeACL
# keys are unique per apikey_prefix
def self.getcredentials(apikey_prefix : String, bcm_serial : String)
success = false
#if the credentials don’t exist yet, they are added
creds = self.first({“client_id” => bcm_serial, “username” => apikey_prefix})
if !creds
creds = self.new()
end(snip)
publish_acl = PublishACL.new()
subscribe_acl = SubscribeACL.new()
# https://vernemq.com/docs/configuration/db-auth.html
publish_acl.pattern = “#”
publish_acl.max_qos = 2 # Int
publish_acl.allowed_retain = truesubscribe_acl.pattern = “#”
subscribe_acl.max_qos = 2
creds.publish_acl << publish_acl
creds.subscribe_acl << subscribe_acl
success = creds.save(snip)
end
end
The ACLs were inserted after I already had database entries without them:
MongoORM error message:
Exception: missing bson key: publish_acl (Exception)
from src/db.cr:0:4 in ‘from_bson’
from lib/mongo_orm/src/mongo_orm/querying.cr:93:7 in ‘all’
from lib/mongo_orm/src/mongo_orm/querying.cr:90:3 in ‘all’(snip)
from /usr/share/crystal/src/fiber.cr:47:34 in ‘->’
from ???
MongoORM does not find the expected fields publish_acl and subscribe_acl, which were added later.
Solution: drop (or upgrade) the documents in the Collection, which do not conform to your new standard.
This is, for instance, how a database entry looks like for the above:
Bonus
in lib/mongo_orm/src/mongo_orm/extended_bson.cr:40: no overload matches ‘BSON#[]=’ with types String, Array(Papi::PublishACL)
Overloads are:
– BSON#[]=(key, value : Int32)
– BSON#[]=(key, value : Int64)
– BSON#[]=(key, value : Binary)
– BSON#[]=(key, value : Bool)
– BSON#[]=(key, value : Float64 | Float32)
– BSON#[]=(key, value : MinKey)
– BSON#[]=(key, value : MaxKey)
– BSON#[]=(key, value : Nil)
– BSON#[]=(key, value : ObjectId)
– BSON#[]=(key, value : String)
– BSON#[]=(key, value : Symbol)
– BSON#[]=(key, value : Time)
– BSON#[]=(key, value : Timestamp)
– BSON#[]=(key, value : Code)
– BSON#[]=(key, value : BSON)
– BSON#[]=(key, value : Regex)
– BSON#[]=(key, value : Mongo::ORM::EmbeddedDocument)
bson[_key] = value
You cannot do this (currently) with MongoORM:
creds.publish_acl = [ publish_acl ]
instead you have to use:
creds.publish_acl << publish_acl