How to update only the first result of a match query in Typedb? - vaticle-typedb

In the schema I have:
define
description sub attribute, value string;
task sub entity, has description;
Now I write the following two transactions into data:
insert
$a isa task;
$b isa task;
So the result of the query match $x isa task is as expected:
{ $x iid 0x826e80048000000000000000 isa task; }
{ $x iid 0x826e80048000000000000001 isa task; }
answers: 2, total (with concept details) duration: 4 ms
Now I want to insert description to only the first task. So I tried:
match $x isa task; limit 1; insert $x has description "Buy Milk";
But this results in an error:
[THW15] Invalid Thing Write: The thing variable '$x' cannot be inserted as a new instance without providing its type (isa).`
But if I tried:
match $x isa task; insert $x has description "Buy Milk";
then it would update both the tasks.
I can do the following:
match $x iid 0x826e80048000000000000000; insert $x has description "Buy Milk";
and it works!
But I wonder if there is a more elegant way to do this.
So question: How can I update the attribute of only the first result of a match in TypeDB?

I think the fundamental problem you have is that you're inserting tasks without identifying them in any way. TypeDB does give you an iid under the hood, but it would be easier for you to reason about if you gave your own ID to each task at the point at which you create them.
With the above insert query, you get a single task and add a description to it. This could be any task, which makes the query not very useful unless you know every single one of your tasks has no description.
If you wanted to insert a task without adding a description just yet, you could add an ID in advance using the schema:
define
description sub attribute,
value string;
id sub attribute,
value string;
task sub entity,
owns id,
owns description;
and the query:
insert
$a isa task, has id "123456789";
$b isa task, has id "987654321";
These are examples, but you now have a way to identify each task rather than finding a random one and adding a description to it.

Related

firestore security: exist and get within the same function does not work

I'm trying to get() a document and then based on the result, to see if another document exists using exists(). However, this fails because the variable that should be storing a string remains an object, namely parentId below.
Observed
It does not convert parentId to a string and it fails when calling exists().
function validateAuth() {
let parentId = get(/databases/$(database)/documents/items/$(resource.data.itemId)).data.parentId
return exists(/databases/$(database)/documents/other-items/$(parentId):$(request.auth.uid))
}
Expected
It should convert parentId to a string so that exists can be performed.
What I've tried
This below works, and the function is able to evaluate when the document ID using parentId exists and doesn't exist.
function validateAuth() {
// let parentId = get(/databases/$(database)/documents/items/$(resource.data.itemId)).data.parentId
let parentId = 'some-id';
return exists(/databases/$(database)/documents/other-items/$(parentId):$(request.auth.uid))
}
Now, I removed the string concatenation below but this still throws an error
function validateAuth() {
// let parentId = get(/databases/$(database)/documents/items/$(resource.data.itemId)).data.parentId
let parentId = 'some-id';
return exists(/databases/$(database)/documents/other-items/$(parentId))
}
The below does not work, and the parentId is still an object when ran in the simulator.
function validateAuth() {
let parentId = get(/databases/$(database)/documents/items/$(resource.data.itemId)).data.parentId;
let parentIdStr = string(parentId);
return exists(/databases/$(database)/documents/other-items/$(parentIdStr):$(request.auth.uid))
}
Error details
I get this error after the console processes it for about 5 ~ 10 seconds, which is a lot longer than if the requests are processed correctly.
Error: Invalid argument provided to call. Function: [exists], Argument: ["||invalid_argument||"]
I couldn't find any documentation about this. Does anyone know if this should work or if there are workarounds?
The part with colon seems to be the problem:
$(parentIdStr):$(request.auth.uid)
Try refactoring that to a single element in path:
$(parentIdStr+':'+request.auth.uid)

Cannot insert data with key in Grakn

I am ingesting data into Grakn and getting this error
There is more than one thing of type [person] that owns the key [949] of type [person-id].
This is my query:
insert $a isa customer, has customer-id "94929", has person-id "949";
This is my schema:
person sub entity,
key person-id;
customer sub person,
key customer-id;
This indicates that there is an entity of type person, or a subtype of type person, that already has the id "949" in the database. If you run the following query, you should find 1 result.
match $x isa person, has person-id "949"; get;

Delete filter record in objectify datastore

i want to delete record where company_id is "****" and gamer_id is "****".
How to write query for this .
public List<CompanyGamer> unfollowcompany(CompanyGamerForm CompanyGamerForm) throws NotFoundException {
String company_id = CompanyGamerForm.getCompany_id();
String gamer_id = CompanyGamerForm.getGamer_id();
Iterable<Key<CompanyGamer>> allKeys = ofy().load().type(CompanyGamer.class).filter("company_id=", company_id).filter("gamer_id=", gamer_id).keys();
ofy().delete().keys(allKeys); }
Please let me know what should be define in return ?
Have a look at the Objectify documentation for Queries https://github.com/objectify/objectify/wiki/Queries at the bottom of section "Executing Queries". "You can query for just keys, which will return Key objects much more efficiently than fetching whole objects"
Iterable<Key<Gamercompany>> allKeys = ofy().load().type(Gamercompany.class).filter("company_id=", compnyid).filter("gamer_id=",gamer_id).keys();
And then you can delete all entities corresponding to the keys:
ofy().delete().keys(allKeys);
Or if you do want to execute the query that returns the entities and not the keys, you could iterate over the Query and do:
ofy().delete().entity(thing); // asynchronous
or
ofy().delete().entity(thing).now(); // synchronous
However it would be less efficient than the first way.

How to get the table name in AWS dynamodb trigger function?

I am new with AWS and working on creating a lambda function on Python. The function will get the dynamodb table stream and write to a file in s3. Here the name of the file should be the name of the table.
Can someone please tell me how to get the table name if the trigger that is invoking the lambda function?
Thanks for help.
Since you mentioned you are new to AWS, I am going to answer descriptively.
I am assuming that you have set 'Stream enabled' setting for your DynamoDB table to 'Yes', and have set up this as an event source to your lambda function.
This is how I got the table name from the stream that invoked my lambda function -
def lambda_handler(event, context):
print(json.dumps(event, indent=2)) # Shows what's in the event object
for record in event['Records']:
ddbARN = record['eventSourceARN']
ddbTable = ddbARN.split(':')[5].split('/')[1]
print("DynamoDB table name: " + ddbTable)
return 'Successfully processed records.'
Basically, the event object that contains all the information about a particular DynamoDB stream that was responsible for that particular lambda function invoke, contains a parameter eventSourceARN. This eventSourceARN is the ARN (Amazon Resource Number) that uniquely identifies your DynamoDB table from which the event occurred.
This is a sample value for eventSourceARN -
arn:aws:dynamodb:us-east-1:111111111111:table/test/stream/2020-10-10T08:18:22.385
Notice the bold text above - test; this is the table name you are looking for.
In the line ddbTable = ddbARN.split(':')[5].split('/')[1] above, I have tried to split the entire ARN by ':' first, and then by '/' in order to get the value test. Once you have this value, you can call S3 APIs to write to a file in S3 with the same name.
Hope this helps.
Please note that eventSourceArn is not always provided. From my testing today, I didn't see eventSourceArn presented in record. You can also refer to the links:
Issue: https://github.com/aws/aws-sdk-js/issues/2226
API: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_Record.html
One way to do it will be via pattern matching in Scala using regex:
val ddbArnRegex: Regex = """arn:aws:dynamodb:(.+):(.+):table/(.+)/stream/(.+)""".r
def parseTableName(ddbARN: String): Option[String] = {
if (null == ddbARN) None
ddbARN match {
case ddbArnRegex(_, _, table, _) => Some(table)
case _ => None
}
}

What is returned from a "await db.Database.ExecuteSqlCommandAsync(sql, parameters)"

I am trying to use this method to call a stored procedure.
var abc = await db.Database.ExecuteSqlCommandAsync(sql, parameters)
I see plenty of information on how to return data using parameters and that works okay. But I cannot find anything that tells me what is returned from the call?
Can someone tell me what will be put into abc and how can it be used?
As per
MSDN Database.ExecuteSqlCommandAsync Method (String, Object[])
it returns Task<int>. Here it is shown:
public Task<int> ExecuteSqlCommandAsync(
string sql,
params Object[] parameters
)
Return Value
Type: System.Threading.Tasks.Task<Int32>
A task that represents the asynchronous operation. The task result contains the result returned by the database after executing the command.
Now it depends on what you have in your sql query (sql param in your case). But for example, if you have a simple DELETE query like:
DELETE student WHERE papertype = 'science'
it will return the number of rows affected by the command. It's not a production level query so please ignore it's quality but you get the idea!

Resources