问题
Update: I use "$match expression" to describe this but I don't actually use the $match operator. According to the docs, the selector should conform with $match's syntax, though the $match keyword is apparently not necessary in the actual expression.
Update 2: In the actual collection, outerField
represents message
, fieldA
represents fansNo
, and fieldB
represents sharedNo
. So outerField.fieldA
represents message.fansNo
and outerField.fieldB
represents message.sharedNo
. This is a stringified representation of the updateDescription
field when the trigger fires (i.e. when I only specify updateDescription.updatedField
in the match expression):
"updateDescription: {\"removedFields\":[],\"updatedFields\":{\"someOtherField\":310,\"message.fansNo\":1,\"updatedAt\":\"2020-06-22T13:29:08.829Z\"}}"
================================================================
Original post:
So I can't understand why it fails to trigger when I specify message.fansNo
and message.sharedNo
in the match expression.
I am setting up a database trigger on updates to a collection, but I'm not able to get my $match expression to work in filtering the change events that cause the trigger to fire. I want to fire the trigger only if one or both of 2 nested fields are present, say fieldA
and fieldB
. These 2 fields are nested inside an object, and the object is the value of a field in each document. Something like this:
// CollectionA schema
{
_id: ...,
outerField: {
fieldA: 1 // or any number
fieldB: 2 // or any number
},
...
}
I have tried using this $match expression below, but the trigger doesn't fire:
{
"$or": [
{
"updateDescription.updatedFields.outerField.fieldA": {"$exists":true}
},
{
"updateDescription.updatedFields.outerField.fieldB":{"$exists":true}
}
]
}
If I remove outerField.<field>
, it works. That is:
{
"$or": [
{
"updateDescription.updatedFields": {"$exists":true}
},
{
"updateDescription.updatedFields":{"$exists":true}
}
]
}
But of course that's not useful to me because the trigger will fire on any update at all.
I would provide a demo but I'm not sure how to create a sample that has database triggers configured. Any help will be appreciated, thanks!
回答1:
So I was able to get around this problem by changing the query to watch for a field that gets updated at the same time but isn't nested. I think the problem with checking for a nested field is that the ChangeEvent
's updateDescription
property doesn't contain the actual nested object that has changed; instead it contains the dot-notation representation of the change. So if you look at Update 2 in my post you'll see that updatedFields
has this value: {\"someOtherField\":310,\"message.fansNo\":1...
instead of {\"someOtherField\":310,\"message\":{\"fansNo\":1...
. By using message.fansNo
in the $match query, Mongo will look for this object shape: {\"message\":{\"fansNo\":1...
, which doesn't match in this case. A "real" solution here could be to escape the .
in message.fansNo
in my match expression, but I couldn't get that to work (see this thread).
So the "solution" that worked for me is really just a workaround that works for my specific use-case: it so happens that someOtherField
is always updated along with message.fansNo
, and someOtherField
isn't nested. So I can match someOtherField
without worrying about nesting. Basically this match expression gives me the results I want:
{
"$or": [
{
"updateDescription.updatedFields.someOtherField": {"$exists":true}
},
{
"updateDescription.updatedFields.someOtherField":{"$exists":true}
}
]
}
Hope this helps someone else!
来源:https://stackoverflow.com/questions/62518308/my-or-selector-in-a-database-trigger-match-expression-doesnt-work-at-the-secon