rethinkdb 'or' filter still returning result even filter params is invalid - rethinkdb

I'm trying to retrieve a result where row 'origin' is equal to 'person' or row 'type' is equal to 'human', below is what I've tried
r.db('identitydb').table('connections').filter(
( { "origin" : "person" } ) | ( { "type" : "human" } )
);
yes it did return but the problem is even if I put an invalid values e.g.
r.db('identitydb').table('connections').filter(
( { "origin" : "persss" } ) | ( { "type" : "humaxxxn" } )
);
it still returns the result above like it simply not filtering. Below is the return result
{ "created_at": "January 06, 2019 | 07:32 AM" , "id":
"99f84427-422b-4768-bed8-4d08fc62ff15" , "origin": "human" , "type":
"person" }
I even tried
r.db('identitydb').table('connections').filter(
( r.row["origin"] == "person" ) | ( r.row["type"] == "human" )
);
but unfortunately, same result. Any help, ideas please?

I am confused that you tagged your question with "rethinkdb-javascript" but your queries are for the python driver. The javascript version of your query works fine:
r.db("identitydb").table("connections")
.filter(r.row("origin").eq("person").or(r.row("type").eq("human")))

Related

Query JSONPath in JQ Format

I have JSONPath:
$.endpointAgents[?(#.clients.userName=~ 'a')].agentId
How it will look in jq format on Linux??
jq '.endpointAgents [] | select(.clients.userName=~"a") | {agentId}')"
does not work.
Code:
{
"endpointAgents": [
{
"agentId": "MyId",
"agentName": "MYNAME",
"location": {
"locationName": "location"
},
"clients": [
{
"userProfile": {
"userName": "Name"
},
"browserExtensions": [
{
"active": false
}
]
}
],
"totalMemory": "16222 MB",
"agentType": "enterprise"
}
]
}
I want to get userName value by specifying agentId
jq '.endpointAgents[] | select(.agentId == "MyId") | .clients[].userProfile.userName'
Will output "Name"
.endpointAgents[]
Loop over each endpointAgent
select(.agentId == "MyId")
Select the objects where .agentId == "MyId"
.clients[].userProfile.userName
Since clients is an array, loop over it, and show .userProfile.userName for each object.
Try it online!
If I understand correctly, you want to produce the agent id of endpoints with a client whose name matches a.
.endpointAgents[] |
select( any( .clients[].userProfile.userName; test("a") ) ) |
.agentId
To produce the agent id of endpoints with a client whose name is equal to a, use the following instead:
.endpointAgents[] |
select( any( .clients[].userProfile.userName; . == "a" ) ) |
.agentId

How to store a custom object in Cassandra?

I have the following object which I need to store in Cassandra. Do I need to use UDT or is there any other way to store the object. I need to finally store this from spring-boot application using Repository approach.
{
"name": "Krishna",
"age" : 24,
"address" : [
{
"attributes" : [
{
"name": "",
"value" : ""
}
],
"contactnumbers" : [ "123123234", "123456"]
}
],
"devices" : [
"android_pixel",
"ios_6s"
]
}
I think, you need to use UDT here. I could come up with this.
CREATE TYPE attribute_info (
name text,
value text
);
CREATE TYPE address_info (
attributes list<frozen<attribute_info>>,
contactnumbers list<text>
);
CREATE TYPE user_info (
name text,
age int,
address list<frozen<address_info>>,
devices list<text>
);
Once you get user_info under your key space, use it as a type for the column while creating or altering the table.

How to give access to certain user groups in cognito using Appsync

I recently got into AWS and I'm using appsync alongside a dynamo table with an idex for user id(from the cognito pool) to give only certain user access to certain data. Now I would like to further expand upon this and also give access to certain cognito groups. Here is my code:
1st. my mutation
## [Start] Prepare DynamoDB PutItem Request. **
$util.qr($context.args.input.put("createdAt", $util.time.nowISO8601()))
$util.qr($context.args.input.put("updatedAt", $util.time.nowISO8601()))
$util.qr($context.args.input.put("__typename", "Patient"))
## This line adds the userId, accessed from the $ctx.identity variable
$util.qr($context.args.input.put("userId", $ctx.identity.sub))
$util.qr($context.args.input.put("Groupi", $ctx.identity.claims.get("cognito:groups")))
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.args.input.id, $util.autoId()))
},
"attributeValues": $util.dynamodb.toMapValuesJson($context.args.input),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id"
}
}
}
and the query
#set( $limit = $util.defaultIfNull($context.args.limit, 10) )
{
"version" : "2017-02-28",
"operation" : "Query",
"limit": $limit,
"index": "userId-index",
"query" : {
"expression": "userId = :userId",
"expressionValues" : {
":userId" : $util.dynamodb.toDynamoDBJson($ctx.identity.sub)
}
},
"nextToken": #if( $context.args.nextToken )
"$context.args.nextToken"
#else
null
#end
}
I would like to expand the query to support t6he group aswell. Help would be much appreciated.
Thanks!
The authorization docs have lots of examples you might find helpful: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html
Specifically, this one:
#set($expression = "")
#set($expressionValues = {})
#foreach($group in $context.identity.claims.get("cognito:groups"))
#set( $expression = "${expression} contains(groupsCanAccess, :var$foreach.count )" )
#set( $val = {})
#set( $test = $val.put("S", $group))
#set( $values = $expressionValues.put(":var$foreach.count", $val))
#if ( $foreach.hasNext )
#set( $expression = "${expression} OR" )
#end
#end
{
"version" : "2017-02-28",
"operation" : "Scan",
"limit": #if(${context.arguments.count}) "${context.arguments.count}" #else 20 #end,
"nextToken": #if(${context.arguments.nextToken}) "${context.arguments.nextToken}" #else null #end,
"filter":{
"expression": "$expression",
"expressionValues": $utils.toJson($expressionValues)
}
}
That example has some extra info since it's about a list call rather than a simple get, however you can see it being set in the expression/expression values. This implementation looks a tad different than what you have as it allows a user to be in multiple groups, any one of which could work.
Does that make sense?
The other examples here seem more attuned to the 'fine grained access control' section, which depending on your needs may be the correct choice:
https://docs.aws.amazon.com/appsync/latest/devguide/security.html#fine-grained-access-control
For more general cases, if you have a look at the 'Security' docs page, there is a good example for how to use directives directly in your GraphQL schema as well:
https://docs.aws.amazon.com/appsync/latest/devguide/security.html#amazon-cognito-user-pools-authorization
In particular for your use case, the #aws_auth or #aws_cognito_user_pools directives seem relevant. The full list is:
#aws_api_key - To specify the field is API_KEY authorized.
#aws_iam - To specify that the field is AWS_IAM authorized.
#aws_oidc - To specify that the field is OPENID_CONNECT authorized.
#aws_cognito_user_pools - To specify that the field is AMAZON_COGNITO_USER_POOLS authorized.
To copy the example from the docs page:
type Query {
posts:[Post!]!
#aws_auth(cognito_groups: ["Bloggers", "Readers"])
}
type Mutation {
addPost(id:ID!, title:String!):Post!
#aws_auth(cognito_groups: ["Bloggers"])
}

Springdata mongodb aggregation match

After asking question to understand a bit more of the aggregation framework in MongoDB I finally found the way to do aggregation for my need (thanks to a StackExchange user)
So basically here is a document from my collection:
{
"_id" : ObjectId("s4dcsd5s4d6c54s6d"),
"items" : [
{
type : "TYPE_1",
text : "blablabla"
},
{
type : "TYPE_2",
text : "blablabla"
},
{
type : "TYPE_3",
text : "blablabla"
},
{
type : "TYPE_1",
text : "blablabla"
},
{
type : "TYPE_2",
text : "blablabla"
},
{
type : "TYPE_1",
text : "blablabla"
}
]
}
The idea was to be able to filter only some elements of my collections (avoiding Type 2 and 3). In fact I have more than 30 types and 6 are not allowed but for simplicity I made this example.
So the aggregation command in command line is this one:
db.history.aggregate([{
$match: {
_id: ObjectId("s4dcsd5s4d6c54s6d")
}
}, {
$unwind: '$items'
}, {
$match: {
'items.type': { '$nin': [ "TYPE_2" , "TYPE_3"] }
}
},
{ $limit: 10 }
]);
With this I am able to retrieve the 10 elements items of this document which do not match TYPE_2 and TYPE_3
However when I am using spring data there is no output. I looked a bit at the example to build mine but its still not working.
So I did:
Aggregation aggregation = newAggregation(
match(Criteria.where("id").is(myID)),
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
AggregationResults<PersonnalHistory> results = mongAccess.getOperation().aggregate(query,
"items", PersonnalHistory.class);
PersonnalHistory is marked with annotation #Document(collection = "history") and id with the #id annotation
ignoreditemstype is a list containing TYPE_2 and TYPE_3
Here is what I have in the toString method of aggregation:
{
"aggregate" : "__collection__" ,
"pipeline" : [
{ "$match": { "id" : "s4dcsd5s4d6c54s6d"} },
{ "$unwind": "$items"},
{ "$match": { "items.type": { "$nin" : [ "TYPE_2" , "TYPE_3" ] } } },
{ "$limit" : 3},
{ "$skip" : 0 }
]
}
I tried a lot of stuff (to have at least an answer :) ) like removing id or the nin:
aggregation = newAggregation(
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
aggregation = newAggregation(
match(Criteria.where("id").is(myid)),
unwind("items")
);
For information when I do a simple query like:
query.addCriteria(Criteria.where("id").is(myID));
My document is returned. However I have thousands of items. So I just want to have the 15 first (in fact the 15 first are the 15 last added)
Do you maybe see what I am doing wrong?
Yeah looks like you are passing simple String while it is expecting ObjectId
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(new ObjectId(myID))),
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
Now the question is why it works with simple query, my answer would be because spring-data driver is not that mature at least not with aggregation pipeline.

Selecting age count without intervals

so what I am trying to is write a query that will return a count of people that are each age - not increments. So the count of people that have been alive for 1, 2, 3, ... 67 ... 99, ... years.
I am not familiar with NoSQL but I know that because time is ongoing, the ages count will have to be periodically updated/refreshed. What I was thinking was to have a collection or something that has a key of the age and the value as the number of people that are the age. When a new person is created, it will increment the amount of people in his or her age - then as I said earlier have something to update it.
What I am trying to figure out is if there is a way to actively fetch the amount of amount of people (real time) of all different ages without having a counter. Or if I must use a counter, how can I have the database automatically increment the counter so I don't need to interact with the program?
You can achieve this by using MongoDB's aggregation framework. In order to keep it up to date in real time, what you need to do is the following:
Project an ageMillis field by subtracting the date of birth (dob) from the current date. You will get an age value in milliseconds.
Divide ageMillis by the number of milliseconds in a year (in JavaScript it is 31536000000) and project this onto an ageDecimal field. You don't want to use this age to group because it contains a decimal.
Project the ageDecimal field and a decimal field containing the decimal portion of the age. You are able to do this using the $mod operator.
Subtract decimal from ageDecimal and project it to an age field. This gives you the age value in years.
Group by the age field and keep track of the count using $sum. Basically you add 1 for every document you see for that age.
If needed, sort by age field.
The command in the mongo shell would look something like the command below, using JavaScript's Date() object to get the current date. If you want to do this in Ruby, you would have to change that bit of code and make sure that for the rest, you follow the syntax for the Ruby driver.
db.collection.aggregate([
{ "$project" :
{
"ageMillis" : { "$subtract" : [ new Date(), "$dob" ]}
}
},
{ "$project" :
{
"ageDecimal" : { "$divide" : [ "$ageMillis", 31536000000 ]}
}
},
{ "$project" :
{
"ageDecimal" : "$ageDecimal",
"decimal" : { "$mod" : [ "$ageDecimal", 1 ]}
}
},
{ "$project" :
{
"age" : { "$subtract" : [ "$ageDecimal", "$decimal" ]}
}
},
{ "$group" :
{
"_id" : { "age" : "$age" },
"count" : { "$sum" : 1 }
}
},
{ "$sort" :
{
"_id.age" : 1
}
}
]);
This should give you the results that you want. Note that the aggregate() method returns a cursor. You will have to iterate through it to get the results.
The aggregation framework is the best approach for this. Mongoid exposes the lower level collection object through a .collection accessor. This allows the native driver implementation of aggregate to be used.
The basic math here is:
Rounded Result of:
( difference from date of birth to now in milliseconds /
number of milliseconds in a year )
Feed the current Time value into your aggregation statement to get the current age
res = Model.collection.aggregate([
{ "$group" => {
"_id" => {
"$subtract" => [
{ "$divide" => [
{ "$subtract" => [ Time.now, "$dob" ] },
31536000000
]},
{ "$mod" => [
{ "$divide" => [
{ "$subtract" => [ Time.now, "$dob" ] },
31536000000
]},
1
]}
]
},
"count" => { "$sum" => 1 }
}},
{ "$sort" => { "_id" => -1 } }
])
pp res

Resources