Neo4j query: conditional match - performance

I have this model:
Bob and Alice are Users
CVI is a clinic
Pluto is an animal
The users have a property called identityId (CONSTRAINT UNIQUE) to identify the user.
I would like to select the User with a given id only if it is the user itself (same identityId) or if it exists a relationship SHARED_WITH between the Alice and Bob.
In terms of performance, is the query below the best query for that?
MATCH (u:User)
WHERE id(u) = {id} AND ((u.identityId = {identityId})
OR ((:User { identityId: {identityId} }) - [:OWNS] -> (:Clinic) <- [:SHARED_WITH] - (u)))
RETURN u
Example
Alice { id: 6, identityId: "5678"}
Bob { id: 3, identityId: "1234"}
Mallory { id: 5, identityId: "2222"}
First case: The caller is Alice
MATCH (u:User)
WHERE id(u) = 6 AND ((u.identityId = "5678")
OR ((:User { identityId: "5678" }) - [:OWNS] -> (:Clinic) <- [:SHARED_WITH] - (u)))
RETURN u
The u is Alice
Second case: The caller is Bob
MATCH (u:User)
WHERE id(u) = 6 AND ((u.identityId = "1234")
OR ((:User { identityId: "1234" }) - [:OWNS] -> (:Clinic) <- [:SHARED_WITH] - (u)))
RETURN u
The u is Alice
Third case: The caller is Mallory
MATCH (u:User)
WHERE id(u) = 6 AND ((u.identityId = "2222")
OR ((:User { identityId: "2222" }) - [:OWNS] -> (:Clinic) <- [:SHARED_WITH] - (u)))
RETURN u
The u is NULL (mallory is neither the user nor the user with Alice has shared its user)

Taking into account your additional explanations:
// Get user by id
MATCH (I:User) WHERE id(I) = {id}
// Whom with given {identityId} shard with him
OPTIONAL MATCH (U:User {identityId: {identityId} })
-[:OWNS]->()<-[:SHARED_WITH]-
(I)
WITH I, COUNT(U) as UC
// Test user {identityId}
// or there are those who with {identityId} are with him shares
WHERE I.identityId = {identityId} OR UC > 0
RETURN I

Related

problems with the leaderboard discord.py

The leaderboard shows the same username even if they are different users in case they have the same value.
I don't know how to solve it but when in the code I ask to resist a variable it gives me only 3 elements and not 4 even if 4 come out.
code:
#client.command(aliases = ["lb"])
async def leaderboard(ctx,x = 10):
leader_board = {}
total = []
for user in economy_system:
name = int(user)
total_amount = economy_system[user]["wallet"] + economy_system[user]["bank"]
leader_board[total_amount] = name
total.append(total_amount)
print(leader_board)
total = sorted(total,reverse=True)
embed = discord.Embed(
title = f"Top {x} Richest People",
description = "This is decided on the basis of raw money in the bank and wallet",
color = 0x003399
)
index = 1
for amt in total:
id_ = leader_board[amt]
member = client.get_user(id_)
name = member.name
print(name)
embed.add_field(
name = f"{index}. {name}",
value = f"{amt}",
inline = False
)
if index == x:
break
else:
index += 1
await ctx.send(embed=embed)
print resists this:
{100: 523967502665908227, 350: 554617490806800387, 1100: 350886488235311126}
Padre Mapper
Flore (Orsolinismo)
Aetna
Aetna
In theory there should also be 100: 488826524791734275 (i.e. my user id) but it doesn't find it.
Your problem comes from this line:
leader_board[total_amount] = name
If total_amount is already a key (eg. two users have the same amount of money), it will replace the previous value (which was a user ID) and replace it with another user ID. In this situation, if multiple users have the same amount of money, only one will be saved in leader_board.
Then, you have this line:
total.append(total_amount)
In this case, if two users have the same amount of money, you would just have two identical values, which is normal but, considering the problem above, this will create a shift.
Let's say you have ten users with two of them who have the same amount of money. leader_board will only contain 9 items whereas total will contain 10 values. That's the reason why you have two of the same name in your message.
To solve the problem:
#client.command(aliases = ["lb"])
async def leaderboard(ctx, x=10):
d = {user_id: info["wallet"] + info["bank"] for user_id, info in economy_system.items()}
leaderboard = {user_id: amount for user_id, amount in sorted(d.items(), key=lambda item: item[1], reverse=True)}
embed = discord.Embed(
title = f"Top {x} Richest People",
description = "This is decided on the basis of raw money in the bank and wallet",
color = 0x003399
)
for index, infos in enumerate(leaderboard.items()):
user_id, amount = infos
member = client.get_user(user_id)
embed.add_field(
name = f"{index}. {member.display_name}",
value = f"{amount}",
inline = False
)
await ctx.send(embed=embed)
If I guessed right and your dictionnary is organized like this, it should work:
economy_system = {
user_id: {"bank": x, "wallet": y}
}

Sort table in lua as multible groups

I need to sort a list _rolls to have both the users rolls and ranks taken into considerations.
_rolls = {
{Username="User1", Roll=50, RankPrio=1},
{Username="User2", Roll=2, RankPrio=3},
{Username="User4", Roll=10, RankPrio=2},
{Username="User5", Roll=9, RankPrio=2},
{Username="User3", Roll=32, RankPrio=2}
}
I want the list to be sorted like
_rolls = {
{Username="User2", Roll=2, RankPrio=3},
{Username="User3", Roll=32, RankPrio=2},
{Username="User4", Roll=10, RankPrio=2},
{Username="User5", Roll=9, RankPrio=2},
{Username="User1", Roll=50, RankPrio=1}
}
i know i can use this to sort by Rolls but i cant see a way to do both.
table.sort(_rolls, function(a,b) return a.Roll < b.Roll end)
You just need to write the comparison function so that it compares the Roll fields when the RankPrio fields compare equal:
_rolls = {
{Username="User1", Roll=50, RankPrio=1},
{Username="User2", Roll=2, RankPrio=3},
{Username="User4", Roll=10, RankPrio=2},
{Username="User5", Roll=9, RankPrio=2},
{Username="User3", Roll=32, RankPrio=2}
}
table.sort(_rolls,
function (a, b)
if a.RankPrio == b.RankPrio then
return b.Roll < a.Roll
else return b.RankPrio < a.RankPrio
end
end)
> table.inspect(_rolls)
1 =
RankPrio = 3
Username = User2
Roll = 2
2 =
RankPrio = 2
Username = User3
Roll = 32
3 =
RankPrio = 2
Username = User4
Roll = 10
4 =
RankPrio = 2
Username = User5
Roll = 9
5 =
RankPrio = 1
Username = User1
Roll = 50

elasticsearch: creating inner queries

here are my logs:
index: purchase
{details: { name: john, corID: 12345678 }}
{details: { name: bill, corID: 96657545}}
{town: NY, ID: 12345678 }
{a:b , v: g}
{a: hi, b: 12345678}
{g:f , k:ggg777 }
I would like to create a query which for a given name, the query will search in purchase index for details.name=<name> , extract details.corID and search in the indexe for logs which contain the details.corID
example for above details:
name = "john"
query result:
(all logs which have 12345678)
{details: { name: john, corID: 12345678 }}
{town: NY, ID: 12345678 }
{a: hi, b: 12345678}
EDIT
this is how I would do it in SQL:
SELECT * FROM purchase
where corID=
(SELECT details.corID
FROM [purchase]
where details.name = "john")

How can I create a Bacon.Property representing a property in a referenced object?

I have started playing with Bacon.js, and I have come across a problem I can't find any example for.
I have a set of nodes, which may reference other nodes.
It looks like this in imperative code:
alice = { name: "Alice" }
bob = { name: "Bob" }
carol = { name: "Carol" }
alice.likes = bob
bob.likes = carol
alice.likes.name //=> "Bob"
bob.name = "Bobby"
alice.likes.name //=> "Bobby"
alice.likes = carol
alice.likes.name //=> "Carol"
Now, I would like to have a Property for alice.likes.name, which has to change
whenever alice.likes points to a different object, or the name property of the
current object in alice.likes changes.
I have come up with the code below (LiveScript syntax), which correctly logs 3 messages: Bob, Bobby, Carol.
I'm using Bus for testing purposes.
mkBus = (initialValue) ->
bus = new Bacon.Bus()
property = bus.toProperty(initialValue)
property.push = (newValue) -> bus.push(newValue)
property
alice = { pName: mkBus("Alice"), pLikes: mkBus(null) }
bob = { pName: mkBus("Bob"), pLikes: mkBus(null) }
carol = { pName: mkBus("Carol"), pLikes: mkBus(null) }
alice.pLikes.onValue (person) ->
if person
person.pName.onValue (vName) ->
console.log vName
alice.pLikes.push(bob)
bob.pLikes.push(carol)
# Change name
bob.pName.push("Bobby")
# Change reference
alice.pLikes.push(carol)
Question: How can I make a Property that represents the name of alice.likes.name?
I.e:
nameOfAlicesFavourite.onValue (vName) ->
console.log vName
I'm new to FRP, so let me know if I'm doing something horribly wrong.
Thanks #Bergi for pointing me to flatMap.
flatMap creates a new stream for every event in the source. I used flatMapLatest, so that only the name changes from the latest liked person are transmitted on the output stream.
Here's the code:
nameOfAlicesFavourite = alice.pLikes.flatMapLatest (person) ->
if person
person.pName
else
Bacon.never!

Querying a parameter that’s not an index on DynamoDb

TableName : people
id | name | age | location
id_1 | A | 23 | New Zealand
id_2 | B | 12 | India
id_3 | C | 26 | Singapore
id_4 | D | 30 | Turkey
keys: id -> hash and age->range
Question 1
I’m trying to execute a query: “Select * from people where age > 25”
I can get it to work queries like “Select age from people where id = id_1 and age > 25” which is not what I need, just need to select all values.
And if I don’t need age to be a range index, how should i modify my query params to just return the list of records matching the criterion: age > 25?
Question 2
AWS throws an error when either Lines 23 or 24-41 are commented.
: Query Error: ValidationException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
status code: 400, request id: []
Is the KeyConditions/KeyConditionsExpressions parameter required? Does it mean that I cannot query the table on a parameter that's not a part of the index?
func queryDynamo() {
log.Println("Enter queryDynamo")
svc := dynamodb.New(nil)
params := &dynamodb.QueryInput{
TableName: aws.String("people"), // Required
Limit: aws.Long(3),
// IndexName: aws.String("localSecondaryIndex"),
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":v_age": { // Required
N: aws.String("25"),
},
":v_ID": {
S: aws.String("NULL"),
},
},
FilterExpression: aws.String("age >= :v_age"),
// KeyConditionExpression: aws.String("id = :v_ID and age >= :v_age"),
KeyConditions: map[string]*dynamodb.Condition{
"age": { // Required
ComparisonOperator: aws.String("GT"), // Required
AttributeValueList: []*dynamodb.AttributeValue{
{ // Required
N: aws.String("25"),
},
// More values...
},
},
"id": { // Required
ComparisonOperator: aws.String("EQ"), // Required
// AttributeValueList: []*dynamodb.AttributeValue{
// S: aws.String("NOT_NULL"),
// },
},
// More values...
},
Select: aws.String("ALL_ATTRIBUTES"),
ScanIndexForward: aws.Boolean(true),
}
//Get the response and print it out.
resp, err := svc.Query(params)
if err != nil {
log.Println("Query Error: ", err.Error())
}
// Pretty-print the response data.
log.Println(awsutil.StringValue(resp))
}
DynamoDB is a NoSQL based system so you will not be able to retrieve all of the records based on a condition on a non-indexed field without doing a table scan.
A table scan will cause DynamoDB to go through every single record in the table, which for a big table will be very expensive in either time (it is slow) or money (provisioned read IOPS).
Using a filter is the correct approach and will allow the operation to complete if you switch from a query to a scan. A query must always specify the hash key.
A word of warning though: if you plan on using a scan operation on a table of more than just a few (less than 100) items that is exposed in a front end you will be disappointed with the results. If this is some type of cron job or backend reporting task where response time doesn't matter this is an acceptable approach, but be careful not to exhaust all of your IOPS and impact front end applications.

Resources