How to create a SNS Filter Policy that matches nested message attributes? - amazon-sns

I've created an SNS topic, and I'd like to subscribe to it with a filter policy that matches a nested attribute. For example, given a message like this:
{
"foo": {
"bar": "baz"
},
"quux": "vorp"
}
I'd like to match only messages where the bar attribute of foo is equal to baz.
The documentation I've found so far only mentions matching attributes specified at the top level. I'm interested in a nested attribute. For the purposes of this question, let's assume I don't control the structure of the message.

Subscription filters don't act on the message (body, payload). They only act on the message attributes.
Message attributes are not complex objects... their only types are string, string array, number, and binary. If a message attribute contains a serialized object (e.g. JSON), subscription filters aren't designed to support extracting/matching the serialized data inside.

As of 2022, it's possible to filter based on the payload.
That's mentioned here:
https://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html
An Example of filtering:
Let's say your original message is like:
{
"eventType": "SOME_STRING",
"otherAttribs": "bla..."
}
Then the filter can be something like:
{
"eventType": [
{
"prefix": "SAMETH"
}
]
}
In AWS WebConsole, it's found in SNS -> Subscriptions -> [select one] -> Subscription filter policy.

Now, SNS can filter events based on their payload as well. With this release, the SNS filter policy can handle property nesting too. For more information, please take a look at: https://aws.amazon.com/blogs/compute/introducing-payload-based-message-filtering-for-amazon-sns/

Related

delete item out of firebase database

I have a restaurant bookmarks list in my firebase, but I don't know how to delete a specific restaurant in my database.
So I have the function unfavorite(favorite) where I pass the favorite restaurant as a parameter. Till here, than I want to pass this parameters id to the query to remove from the database like this:
this.afDb.list(`bookmarks/${user.uid}/restaurant/${favorite.restaurant.id})`).remove();
here is a screenshot of my database list:
How can I remove that specific restaurant out of the bookmarks list?
You will first need to add an ".indexOn": ["id"] rule to your database something like this:
"bookmarks": {
"$user_id": {
// normal reads and write rules here
},
".indexOn": ["id"]
This step is necessary for firebase database because otherwise you wont be able to use the orderByChild() and equalTo() methods.
Then, where you have your delete function, you want to instead use:
exampleRef = yourDb.ref("bookmarks/${user.uid}"); //this is just to simplify your reference a bit
exampleRef.orderByChild('id').equalTo(theDeleteIDhere).once('value').then(snapshot => {
snapshot.forEach((restaurant) => {
restaurant.ref.remove();
});
}); //this is a Promise that you can modify to return "true" if successful for example
The example I provided is just the way I have done it before (i.e. I prefer to use promises; hence the then() becuase this makes it easier to return that promise in an angular service which allows me to check whether the request was successful). You can use any variation of this so long as you have the "indexOn" rule and you use any sort of "sorting" method firebase provides here
Method 2
When I wrote this I totally glanced over the ability to map your restaurants like such:
Lets say your project is already listing those restaurants. You can therefore save each restaurant's auto generated id to a variable or map:
restaurants; // this is a map like this <your-identifier:autoID>
you can then easily just call:
exampleRef.child(restaurants[yourIdentifier]).remove();

Users sees one part of deeply-nested state, should visible properties be at top level?

I'm working on a game. Originally, the user was in a single dungeon, with properties:
// state
{
health: 95,
creatures: [ {}, {} ],
bigBoss: {},
lightIsOn: true,
goldReward: 54,
// .. you get the idea
}
Now there are many kingdoms, and many dungeons, and we may want to fetch this data asynchronously.
Is it better to represent that deeply-nested structure in the user's state, effectively caching all the other possible dungeons when they are loaded, and every time we want to update a property (e.g. action TURN_ON_LIGHT) we need to find exactly which dungeons we're talking about, or to update the top-level properties every time we move to a new dungeon?
The state below shows nesting. Most of the information is irrelevant to my presentational objects and actions, they only care about the one dungeon the user is currently in.
// state with nesting
{
health: 95,
kingdom: 0,
dungeon: 1,
kingdoms: [
{
dungeons: [
{
creatures: [ {}, {} ],
bigBoss: {},
lightIsOn: true,
goldReward: 54
}
{
creatures: [ {}, {}, {} ],
bigBoss: {},
lightIsOn: false,
goldReward: 79
}
{
//...
}
]
}
{
// ...
}
]
}
One of the things that's holding me back is that all the clean reducers, which previously could just take an action like TURN_ON_LIGHT and update the top-level property lightIsOn, allowing for very straight-forward reducer composition, now have to reach into the state and update the correct property depending on the kingdom and dungeon that we are currently in. Is there a nice way of composing the reducers that would keep this clean?
The recommended approach for dealing with nested or relational data in Redux is to normalize it, similar to how you would structure a database. Use objects with IDs as keys and the items as values to allow direct lookup by IDs, use arrays of IDs to indicate ordering, and any other part of your state that needs to reference an item should just store the ID, not the item itself. This keeps your state flatter and makes it more straightforward to update a given item.
As part of this, you can use multiple levels of connected components in your UI. One typical technique with Redux is to have a connected parent component that retrieves the IDs of multiple items, and renders <SomeConnectedChild itemID={itemID} /> for each ID. That connected child would then look up its own data using that ID, and pass the data to any presentational children below it. Actions dispatched from that subtree would reference the item's ID, and the reducers would be able to update the correct normalized item entry based on that.
The Redux FAQ has further discussion on this topic: http://redux.js.org/docs/FAQ.html#organizing-state-nested-data . Some of the articles on Redux performance at https://github.com/markerikson/react-redux-links/blob/master/react-performance.md#redux-performance describe the "pass an ID" approach, and https://medium.com/#adamrackis/querying-a-redux-store-37db8c7f3b0f is a good reference as well. Finally, I just gave an example of what a normalized state might look like over at https://github.com/reactjs/redux/issues/1824#issuecomment-228609501.
edit:
As a follow-up, I recently added a new section to the Redux docs, on the topic of "Structuring Reducers". In particular, this section includes chapters on "Normalizing State Shape" and "Updating Normalized Data".

Meteor publish null or un-named record set

Being new to javascript and surly baby in Meteor. I could not make sense reading this part of the docs. about Meteor.publish(name, func)
Arguments
name String
Name of the record set. If null, the set has no name, and the record set is automatically sent to all connected clients.
I take it that record set means Meteor Collection, if that is correct, then how can a publish action take place on a collection with name "null" or even a collection with no name as stated? I mean, where is the collection to publish if the first parameter "that collection name" is null or does not exist? Thanks
The name parameter in Meteor.publish has absolutely nothing to do with the collection. While the convention is that you should have similar naming to what collection(s) you're using, you could literally call a publish function "asdjfsaidfj" and it would be valid. As yudap said, what data you're sending to the client is entirely determined in the function. You can also return data from multiple collections using an array:
return [
ExampleCollection.find(),
AnotherCollection.find()
];
If you publish data with null argument:
Meteor.publish(null, func)
Basically it is the same as you autopublish without autopublish package. That's mean you don't need to subscribe and you don't need to install autopublish package. The data is ready in client and reactive and you can use it in whatever template without subscribing.
where is the collection to publish? Whatever collection you want to autopublish. Just define it in func:
Meteor.publish(null, function () {
CollectionName.find({}, {
/*
sort: Sort specifier,
skip: Number,
limit: Number,
fields: Field specifier,
reactive: Boolean,
transform: Function
*/
});
});

Meteor parameters and where they come from

I have a question where all the parameters for the meteor functions are coming from? Things like postAttribues, id, postId, limit, etc, etc...
Meteor.publish('newPosts', function(limit) {
return Posts.find({}, {sort: {submitted: -1}, limit: limit});
});
Meteor.publish('singlePost', function(id) {
return id && Posts.find(id);
});
//related to post
Meteor.publish('comments', function(postId) {
return Comments.find({postId: postId});
});
Are they signaled from Mongo DB? It's fine and dandy to memorize these things, but it would be nice to know where these parameters are coming from and what parameters are usually available to me.
I never used any frameworks before, so this may be why I'm confused. I worked exclusively with Javascript before jumping on Meteor.
I also have the same question about Iron Router: When creating a route, we can set a route with a specific Id with /randomName/:_id and the unique code that's responsible for associating the ":_Id" with the actual page is this.params._id. Why and how does the back end associate these things?
I would appreciate any help to help me understand this better.
A meteor find() query follows the syntax find({query}, {options}) defined here: http://docs.meteor.com/#/full/find where the options parameter is an object containing sort, limit, etc... These options look similar to some Mongo operators such as .sort() and .limit() but are defined
The parameters limit and sort are part of the options parameter. It would be useful to review the documentation for Meteor found here: https://docs.mongodb.org/manual/
The parameter postId comes from the way you have defined your objects in your DB. This field is part of your query parameter which specifies what exactly to find in the DB. So by specifying a postId:, Meteor will look through your Comments collection for any containing the postId that you pass. When you pass a string as the query parameter, it is expected that that string is an _id in your collection.
For the parameters being passed into the publication itself see docs.meteor.com/#/full/meteor_subscribe . It comes from the subscription. Basically, you can pass. Parameters between the client and the server this way. To make your publication more robust, you can add parameters as you wish so that the client can specify which 'id' or 'limit' that they want.
As for your iron:router question, I am not sure exactly what you are asking about how the backend associates parameters and the page itself. Perhaps you could be more specific and update your question accordingly

core-ajax accessing firebase data created with push()

When first building my app, I had manually created data and it looked similar to this:
{
"data": {
0: {
"author": "gracehop",
"title": "Announcing COBOL, a New Programming Language"
},
1: {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
I could retrieve the data using core-ajax and iterate through a custom component without problem, like this:
<template is="auto-binding">
<core-ajax id="ds" auto url="https://mysite.firebaseio.com/data.json" response="{{data}}"></core-ajax>
<my-items items="{{data}}"></my-items>
</template>
However, now I'm attempting to create new data in my app using push(). The problem is that the new data looks like this:
{
"data": {
"-JRHTHaIs-jNPLXOQivY": {
"author": "gracehop",
"title": "Announcing COBOL, a New Programming Language"
},
"-JRHTHaKuITFIhnj02kE": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
This lines up with their documentation, which states
Your first instinct might be to use set() to store children with
auto-incrementing integer indexes ... Firebase provides a push()
function that generates a unique ID every time a new child is added to
the specified Firebase reference. By using unique child names for each
new element in the list, several clients can add children to the same
location at the same time without worrying about write conflicts. The
unique ID generated by push() is based on a timestamp, so list items
will automatically be ordered chronologically.
After pushing an item or two, I no longer see any items in my list. If I delete anything created using push() the other items show up again.
Instead of using the core-ajax element, you should be using the native firebase-element. You can then connect it with your data by assigning the location attribute to your unique Firebase URL, then access the data with the data attribute. Likewise, if you are interested in looping through your data, you will need to access the keys attribute since Polymer currently only iterates through arrays.
Your firebase element would look something like this:
<firebase-element id="base" location="https://YOUR.firebaseio.com/"
data="{{data}}" keys="{{keys}}"></firebase-element>
You would then access it like so:
<template repeat="key in keys">
<p>This is your uniqueId generated keys: {{keys}}</p>
<p>This is the data in the keys: {{data[key]['author']}}</p>
</template>
Here is the ref: http://polymer.github.io/firebase-element/components/firebase-element/
The items are not missing or deleted. Indeed if you check out your account dashboard, you'll see both the numeric indices and the push ids. What happens is related to Firebase's handling of array-like data. (You'll want to give that a serious read to understand this)
Essentially, since you've used sequential, numeric ids, the data is treated as an array and returned as an array. But when you add a string as a key, it decides this is now a hash of key/value pairs and treats it as pojo/json data (rightly so).
I don't know much (anything) about Polymer, but I'm guessing that method accepts an array and does not iterate object keys. Thus, you'll need to iterate that data as an object and not an array.

Resources