I'm using PyMongo and PyMODM to work with a fairly simple document structure.
This is what my model is like:
class User(MongoModel):
subscriber_uid: fields.CharField = fields.CharField(required=True)
interface: fields.CharField = fields.CharField(required=True)
...other fields...
class Meta:
"""Defines MongoDB options for this model"""
cascade = True # currently nothing to cascade deletes against
indexes = [
IndexModel(
keys=[('subscriber_uid', pymongo.ASCENDING),
('interface', pymongo.ASCENDING)],
unique=True,
),
]
My unit test looks like this, note that DB is an API which wraps the actual PyMongo commands. eg: put_user
wraps user.save()
in some exception handling logic, while read_user
wraps User.objects.get()
.
...
user = User(**TEST_USER)
user.interface = '2/2/2/2'
user.subscriber_uid = 'some other suid'
DB.put_user(user)
user_from_db = DB.read_user(subscriber_uid=user.subscriber_uid,
interface=user.interface)
assert user_from_db.interface == user.interface
assert user_from_db.subscriber_uid == user.subscriber_uid
# attempt to create a new record with a non-unique suid+iface pair
# ie: ensure this updates instead of creates
user = User(**TEST_USER)
user.someotherattr = 1023
DB.put_user(user)
user_from_db: User = DB.read_user(subscriber_uid=user.subscriber_uid,
interface=user.interface)
assert user_from_db.seed_index == user.seed_index
...
When I run this test, the read_user()
/User.objects.get()
call fails with a MultipleObjectsReturned
objects returned error and I can confirm that there are two records with identical interface
and subscriber_uid
values.
From what I've seen in other StackOverflow answers and comments, the compound unique index above should prevent that from happening.
The database is being dropped on every test run, so the problem isn't stale data lingering. Am I misunderstanding the compound index?