RethinkDB: How to do recursive joins on three tables? - rethinkdb

I am developing a platform with JSON API using Python Flask. In some cases I need to join three tables. How to join tables with a array of IDs gave me some guidance but I need a solution beyond it.
Let's assume we have three tables for a messaging app.
Accounts
Conversations
Messages
Message Readers
Accounts table snippet
{
"id": "account111",
"name": "John Doe",
},
Conversations table snippet
{
"id": "conversation111",
"to": ["account111", "account222", "account333"], // accounts who are participating the conversation
"subject": "RethinkDB",
}
Messages table snippet
{
"id": "message111",
"text": "I love how RethinkDB does joins.",
"from": "account111", // accounts who is the author of the message
"conversation": "conversation111"
}
Message Readers table snippet
{
"id": "messagereader111",
"message": "message111",
"reader": "account111",
}
My question is "What's the magic query to get the document below when I receive a get request on an account document with id="account111"?"
{
"id": "account111",
"name": John Doe,
"conversations": [ // 2) Join account table with conversations
{
"id": "conversation111",
"name": "RethinkDB",
"to": [ // 3) Join conversations table with accounts
{
"id": "account111",
"name": "John Doe",
},
{
"id": "account222",
"name": "Bobby Zoya",
},
{
"id": "account333",
"name": "Maya Bee",
},
]
"messages": [ // 4) Join conversations with messages
{
"id": "message111",
"text": "I love how RethinkDB does joins.",
"from": { // 5) Join messages with accounts
"id": "account111",
"name": "John Doe",
},
"message_readers": [
{
"name": "John Doe",
"id": "account111",
}
],
},
],
},
],
}
Any guidance or advice would be fantastic. JavaScript or Python code would be awesome.

I had a hard time understanding what you want (you have multiple documents with the id 111), but I think this is the query you are looking for
Python query:
r.table("accounts").map(lambda account:
account.merge({
"conversations": r.table("conversations").filter(lambda conversation:
conversation["to"].contains(account["id"])).coerce_to("array").map(lambda conversation:
conversation.merge({
"to": conversation["to"].map(lambda account:
r.table("accounts").get(account)).pluck(["id", "name",]).coerce_to("array"),
"messages": r.table("messages").filter(lambda message:
message["conversation"] == conversation["id"]).coerce_to("array").map(lambda message:
message.merge({
"from": r.table("accounts").get(message["from"]).pluck(["id", "name",]),
"readers": r.table("message_readers").filter(lambda message_reader:
message["id"] == message_reader["message"]).coerce_to("array").order_by(r.desc("created_on")),
})).order_by(r.desc("created_on"))
})).order_by(r.desc("modified_on"))
})).order_by("id").run(db_connection)

Related

Delete existing Records if they are not in sent array Rails 5 API

I need help on how to delete records that exist in the DB but not in array sent in a request;
My Array:
[
{ "id": "509",
"name": "Motions move great",
"body": "",
"subtopics": [
{
"title": "Tywan",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
},
{
"title": "Transportations Gracious",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
},
{
"title": "Transportation part",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
}
]
},
{
"name": "Motions kkk",
"body": "",
"subtopics": [
{
"title": "Transportations",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
}
]
}
]
Below is my implementation: where am going wrong?
#topics = #course.topics.map{|m| m.id()}
#delete= #topics
puts #delete
if Topic.where.not('id IN(?)', #topics).any?
#topics.each do |topic|
topic.destroy
end
end
it's not clear to me where, in your code, you pick the ids sent in the array you showed before... so I'm assuming like this:
objects_sent = [
{ "id": "509",
"name": "Motions move great",
"body": "",
"subtopics": [
{
"title": "Tywan",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
},
{
"title": "Transportations Gracious",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
},
{
"title": "Transportation part",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
}
]
},
{
"name": "Motions kkk",
"body": "",
"subtopics": [
{
"title": "Transportations",
"url_path": "https://ugonline.s3.amazonaws.com/resources/6ca0fd64-8214-4788-8967-b650722ac97f/WhatsApp+Audio+2021-09-24+at+13.57.34.mpeg"
}
]
}
]
since you have your array like this, the only information you need to query on database is the ids (also, assuming the id's in the array are the id's on database, otherwise it wouldn't make sense). You can get them like this:
sent_ids = objects_sent.map{|o| o['id'].to_i}
Also, it seems to me that, for the code you showed, you want to destroy them based on a specific course. There would be 2 ways to do that. First, using the relationship (I prefer like this one):
#course.topics.where.not(id: sent_ids).destroy_all
Or you can do the query directly on the Topic model, but passing the course_id param:
Topic.where(course_id: #course.id).where.not(id: sent_ids).destroy_all
ActiveRecord is smart enough to mount that query correctly in both ways. Give it a test and see which works better for you

Microsoft bot framework for teams capturing unique user id

We are building a product integration using ms teams and ms bots. We are having an existing integration with Slack already. In the slack World we identify a unique user by TEAM_ID and USER_ID . In case of Teams I can see even id in the from node is a very long string suggesting its unique. Below payload is one example coming to our server. Can someone confirm if using id from the from node is wont change a particular user ever?
the user id being assumed unqiue to a user below is "29:1374Bmi6ngJLBlF9oGVcDuTaBbMfJmcOF9eUvQVdx_rgYh5spPNQ5Mi6fLdVvCiT7mQPMNytT0zGk_iAUtvqKAwXXXX"
{
"_activity": {
"id": "1576102076169",
"from": {
"id": "29:1374Bmi6ngJLBlF9oGVcDuTaBbMfJmcOF9eUvQVdx_rgYh5spPNQ5Mi6fLdVvCiT7mQPMNytT0zGk_iAUtvqKAwXXXX",
"name": "My Name",
"aadObjectId": "37a2516a-baf2-41d8-a406-a067888d676c"
},
"conversation": {
"conversationType": "personal",
"tenantId": "9bfb3569-994e-4908-855c-c7f6c1a94100",
"id": "a:1DcGjCAgiuinvuzR0Mx6dR9uJOB3YUwjMdLOiGTAwQ7KWSGsiEijNfvir66ep7k0fABwoSXxCAACx2_3GflfTNIZL7XMkfjrMm0v8OzJJ7vvIFKasqrClrZ_T-8dDfdT0"
},
"channelData": {
"tenant": {
"id": "9bfb3569-994e-4908-855c-c7f6c1a94100"
}
},
"text": "contact mat",
"textFormat": "plain",
"type": "message",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer/",
"recipient": {
"id": "28:a835cf1d-83a8-4ae9-845a-23a68a1df442",
"name": "FlashCX.ai"
}
}
}
#Moblize IT Yes the id obtained from activity.from.id is the unique id for user and it wont change.

Access control at property level (hiding/showing properties in api response based on the role)

I have a spring-boot based micro-service generated using JHipster.
I am using keycloak as my Auth Server. I could enable Role-based & scope based authorization on my resources(apis).
Now the requirement is: based on the role of the client, I need to restrict the information to send in the response (either mask the attributes or nullify them).
eg:
consider the following api to get the person's profile
/api/person/{id}
{
"name": {
"firstName": "Jack",
"lastName": "Sparrow"
},
"gender": "MALE",
"emails": {
"details": [
{
"emailId": "jack.sparrow#gmail.com"
}
]
},
"phones": {
"details": [
{
"phoneNumber": "1234567890",
"countryCode": "+1"
}
]
},
"addresses": {
"details": [
{
"addressLine1": "aaaaaaaa",
"addressLine2": "bbbbbbb",
"city": "cccccc",
"state": "ddddd",
"country": "South Africa",
"postalCode": "987654"
}
]
},
"photo": "string",
"nationality": "South Africa",
"countryOfResidence": "string",
"active": true,
"createdAt": 1537431339569,
"modifiedAt": 1537436600693,
"createdBy": "admin",
"modifiedBy": "admin"
}
Now, when a person with BASIC role calls this API, the requirement is to show only basic information like:
- name, gender
If he has INTERMEDIATE role then we can send something more than basic but not full information. eg: name, gender, photo, nationality
If he has ADMIN role then we can send the complete information.
Can anyone please let me know What is the best approach to achieve this.
-- Thanks in advance :)

YQL console gives me result but rest query gives me error

I'm trying to use YQL Console to get currency rates, the YQL statement is
select * from yahoo.finance.xchange where pair in ("EURUSD","GBPUSD")
the console results give me
{
"query": {
"count": 2,
"created": "2017-10-26T02:42:44Z",
"lang": "en-US",
"results": {
"rate": [
{
"id": "EURUSD",
"Name": "EUR/USD",
"Rate": "1.1829",
"Date": "10/26/2017",
"Time": "3:42am",
"Ask": "1.1829",
"Bid": "1.1829"
},
{
"id": "GBPUSD",
"Name": "GBP/USD",
"Rate": "1.3269",
"Date": "10/26/2017",
"Time": "3:42am",
"Ask": "1.3269",
"Bid": "1.3269"
}
]
}
}
}
but the rest query gives me error
{"error":{"lang":"en-US","diagnostics":{"cache":{"execution-start-time":"0","execution-stop-time":"0","execution-time":"0","method":"GET","type":"MEMCACHED","content":"ENV.queryyahooapiscomproductionsg3.store://datatables.org/alltableswithkeys.15a841ff462a38eb6175e73b4dc747ef"},"env":"Failed to read from storage: store://datatables.org/alltableswithkeys: Invalid store url: store://datatables.org/alltableswithkeys","warning":"Invalid environment specified: store://datatables.org/alltableswithkeys"},"description":"No definition found for Table yahoo.finance.xchange"}}
The yahoo.finance.xchange is a community table. In the YQL console there should be a checkbox saying Show Community Tables select that and you should have access to it. The REST call here works. Let me know if you have any questions.

Use a many to many relation in Elasticsearch

Currently we have a problem to perform a query (or more precisely to design a mapping) in elasticsearch, which help us to perform a query over a relational problem, that we didn't get solved with our non-document orientated thinking from sql.
We want to create a many-to-many relation between different Elasticsearch entries. We need this to edit an entry once and keep all using’s updated to this.
To describe the problem, we'll use the following simple data model:
Broadcast Content
------------ ---------
Id Id
Day Title
Contents [] Description
So we have two different types to index, broadcasts and contents.
A broadcast can have many contents and single contents could also be part of different broadcasts (e.g. repetition).
JSON like:
index/broadcasts
{
"Id": "B1",
"Day": "2014-10-15",
"Contents": [
"C1",
"C2"
]
}
{
"Id": "B2",
"Day": "2014-10-16",
"Contents": [
"C1",
"C3"
]
}
index/contents
{
"Id": "C1",
"Title": "Wake up",
"Description": "Morning show with Jeff Bridges"
}
{
"Id": "C2",
"Title": "Have a break!",
"Description": "Everything about Android"
}
{
"Id": "C3",
"Title": "Late Night Disaster",
"Description": "Comedy show"
}
Now we want to rename the "Late Night Disaster" into something more precisely and keep all references up to date.
How could we approach this? Are there fourther options in ES, like includes in RavenDB?
Nested objects or child-parent relations didn't helped us so far.
What about denormalizing? seems difficult if we come from the SQL mindset, but give you a try, even with millions of documents, LUCENE indexing can help, and renaming will be a batch job.
[
{
"Id": "B1",
"Day": "2014-10-15",
"Contents": [
{
"Title": "Wake up",
"Description": "Morning show with Jeff Bridges"
},
{
"Title": "Have a break!",
"Description": "Everything about Android"
}
]
},
{
"Id": "B2",
"Day": "2014-10-16",
"Contents": [
{
"Title": "Wake up",
"Description": "Morning show with Jeff Bridges"
},
{
"Title": "Late Night Disaster",
"Description": "Comedy show"
}
]
}
]

Resources