Appsync how to use [String] inside query - aws-appsync

I am trying to get products using specific brand names. I have set up my query as brandList : [String]
and the query is as follows
{
"terms": {
"brand_name":
$brandList
}
},
I am not sure how can I pass my query to Appsync. the original query should be like this
"["brand1","brand2","brand3"]". how can I handle the list of string with just brand name.

To be able to execute a query by filtering with an "in" operator it is only possible by using the enhanced filters (or by using the request mapping template).
I suggest you look here: https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html

Related

Calling API through Azure Data Factory

I have to get the values of parameter by calling REST API. I need to fetch the parameters from database for which I need to get the value.
How can I pass the parameters from database.
You could use a Lookup activity to first query your database and get whatever value you want to get. You will be able to access this returned value in the lookup in your next steps. Parameterize your REST API linked service/dataset. You can pass in the value returned by the Lookup activity to this dataset parameter.
First, check if you are using firstRowOnly or your lookup is returning multiple rows. If it is returning multiple rows, you need to keep your next step in a forEach loop.
If your lookup activity is returning two rows, you get the output like shown below.
{
"count": 2,
"value": [
{
"enrollment_number": "123445"
},
{
"enrollment_number": "345678"
}
]
}
ADF Expression for URL would be this:
RemainingUrl/#{activity(activity_name).output.value.enrollment_number}

Reverse JSON query: find all queries in a collection matching an object

I am designing a generic notification subscription system where user can specify a compound rule at the time of subscription in terms of MongoDB query, or more generally, json query. The subscription data is stored in MongoDB collection. For example,
{ "userId": 1, "rule": {"p1": "a"} }
{ "userId": 2, "rule": {"p1": "a", "p2": "b"} }
{ "userId": 3, "rule": {"p3": {$gt: 3} } }
Later when an event in the form of a json object, such as the following, arrives, I want to find all user rules the event maches:
{"p1": "a", "p3": 4}
The above event should match rules specified by userId 1 and 3 in the example. The event object doesn't have to be stored in MongoDB.
Although I can probably meet the requirement by writing a loop at application layer. For efficiency I really want to implement it at db layer, preferably allow distributed (sharded) execution due to volume and latency requirement.
Is it achievable? Any help is appreciated. In fact, I am open to other NOSQL dbs as long as supporting dynamic event schema and there is a way to specify compound rule.
What you are trying to achieve is not possible, at least in MongoDB.
If you reason about how a query engine works, you will realize that this has not a straightforward solution.
On high-level terms, the engine will generate a condition object from your query that then will get evaluated against each document in the set that will result in a boolean value which determines if the document belongs to the result set or not.
In your case you want to do the other way round, you want to generate a condition object based on the document and then apply it to something (e.g an object) that you give it.
Even if it were possible, the cost of doing this on the DB would be too high as it would require to compile an expression function for each object and execute it and there would be no way to optimize the execution of the query.
It is more reasonable to actually do that outside the database, where you could have the expression functions already created.
You cant store "Comparison Query Operators" in a mongo database, but you can do this:
{ "userId": 1, "rule": {"p1": "a"} }
{ "userId": 2, "rule": {"p1": "a", "p2": "b"} }
{ "userId": 3, "rule": {"p3": {"value": 3, "operator":"gt"} } }
You store value AND OPERATOR, in string form, and you can make a query like this:
db.test.find({"rule.p3.comparator":"gt", "rule.p3.value":{$lt:4}})
Notice, if your "operator" is "gt", you must use $lt (the opposite comparison operator) in the query
Your complete example is something like this:
db.test.find({$or:[{"rule.p3.comparator":"gt", "rule.p3.value":{$lt:4}}, {"rule.p1":"a"}]})
This query match userId 1 and 3 like you want
Update: Following solution doesn't work. Problem with mongodb is that it doesn't use NodeJs to run map-reduce javascript, nor support any package manager. So it's hard to use any 3rd party libraries.
My own proposed solution, which hasn't been confirmed :
Compose query conforming to json-query syntax
upon arrival of evt, call MongoDB mapReduce function on user rules collection to invoke jsonQuery in mapper
var jsonQuery = require('json-query')
var mapper = function(evt) {
function map() {
if(jsonQuery(this.rule, {data: evt}){
emit(this.userId);
}
}
return map;
};
db.userRules.mapReduce(mapper(evt), ...);
The reason to compose query into json-query syntax instead of MongoDB query syntax is only json-query offers the jsonQuery method that tries to match one rule to one object. For above code to meet the requirements in question, following assumptions have to be met:
MongoDB can execute mapReduce on distributed nodes
In mapReduce I can use external library such as json-query, which implies the library code has to be distributed to all MongoDB nodes, perhaps as a result of closure.

Mongodb query how to get createdby records or associated with records

My user database structure is as follows
{ _id:123, fname:Name,
projects:[
{projectid:123,
createdby:123}
]
}
{ _id:456, fname:Name,
projects:[
{projectid:789,
createdby:456,
teammembers:[{memberid:123},{memberid:654}]
}
]
}
I am trying to get the list of projects where either i am the creator or i am one of the teammembers. I have trued the following query
db.user.find({"$or":[{"projects.teammembers.memberid":"123"},{"projects.createdby":"123"}],{projects:1})
This query gives me projects where i am not a member also.
If i put the column restriction as
projects.$.memberid:1
mongo throws this error.
"Positional operator does not match the query specifier."
I know by changing the structure of projects.teammembers to just array will work but for now the change process will take time.
Any solution?
You are trying to execute a query on a "2 levels array" that's why you get :
projects.$.memberid:1
So, you must to use the $ proection operator, for "search in each table values in their own table".
Try with
db.user.find({"$or":[{"projects.teammembers.$.memberid":"123"},{"projects.createdby":"123"}],{projects:1})
Or take a look at this doc: Projection doc
Sorry for my english
I was able to solve the problem using aggregate command.
Here's what i did
collection.aggregate([{"$unwind":"$projects"},
{"$match":{"$or":[{"projects.createdby":"user1"},
{"projects.teammembers.memberid":"user1"}]}},
{"$project":{"projects":1}}]
It gives the list of projects where i am the creator and also only those list of projects where i am a team member.

MongoDB selection with existing value

I'm using PyMongo to fetch data from MongoDB. All documents in the collection look like the structure below:
{
"_id" : ObjectId("50755d055a953d6e7b1699b6"),
"actor":
{
"languages": ["nl"]
},
"language":
{
"value": "nl"
}
}
I'm trying to fetch all the conversations where the property language.value is inside the property actor.languages.
At the moment I know how to look for all conversations with a constant value inside actor.languages (eg. all conversations with en inside actor.languages).
But I'm stuck on how to do the same comparison with a variable value (language.value) inside the current document.
Any help is welcome, thanks in advance!
db.testcoll.find({$where:"this.actor.languages.indexOf(this.language.value) >= 0"})
You could use a $where provided your query set is small, but any real size and you could start seeing problems, especially since this query seems like one that needs to be run in realtime on a page and the JS engine is single threaded among other problems.
I would actually consider a better way in this case is through the client side, it is quite straight forward, pull out records based on one of the values, iterate and test their conditional double value (i.e. pull out based on language.value being nl and test actor.languages value for that previous value).
I would imagine you might be able to do this with the aggregation framework however, at the min you cannot use computed fields within $match. I would imagine it would look like this:
{$project:
{languages_value: "$language.value", languages: "$actor.languages"}
}, {$match: {"$languages": {$in:"$languages_values"}}
If you could. But there might be a way.

MongoDB Aggregate $project

I store our web server logs in MongoDB and the schema looks similar to as follows:
[
{
"_id" : 12345,
"url" : "http://www.mydomain.com/xyz/abc.html",
....
},
....
]
I am trying to use the $project operator to reshape this schema a little bit before I start passing my collection through an aggregation pipeline. Basically, I need to add a new field called "type" that will later be used to perform group-by. The logic for the new field is pretty simple.
if "url" contains "pattern_A" then set "type" = "sales lead";
else if "url" contains "pattern_B" then set "type" = "existing client";
...
I'm thinking it would have to be something like this:
db.weblog.aggregate(
{
$project : {
type : { /* how to implement the logic??? */ }
}
}
);
I know how to do this using map-reduce (by setting the "keyf" attribute to a custom JS function that implements the above logic) but am now trying to use the new aggregation framework to do this. I tried to implement the logic using the expression operators but so far couldn't get it to work. Any help/suggestion would be greatly appreciated!
I am sharing my "solution" in case others encounter the same needs like mine.
After researching for a couple of weeks, as #asya-kamsky suggested in one of his comments, I've decided to add a computed field to my original MongoDB schema. It's not ideal because whenever the logic for the computed field changes I would have to do bulk updates to update all documents in my collection but it was either that or rewrite my code to use MapReduce. I chose the former for now. In looking at MongoDB Jira board, it would appear that many people have asked for more diverse operators to be added for the $project operator and I certainly hope that the MongoDB dev team gets around to adding them sooner than later
Operator for splitting string based on a separator.
New projection operator $elemMatch
Allow $slice operator in $project
add a $inOrder operator to $project
You need to use combination of several operators and expressions.
first, the $cond operator in $project lets you implement if then else logic.
$cond : takes an array of three elements, first a boolean expression, second and third are values to use for the field value - if boolean expression is true then it uses second element for value, if not then third element.
you can nest these so that third element is itself a $cond expression to get if-then-else-if-then-etc.
string manipulation is a little awkward but you do have $substr available.
If you post some examples of what exactly you tried, I may be able to spot why it didn't work.