Graphql how to create a complex filter - sql

I am creating an app where teachers can search for resources. Each resource is tagged with topics that are used to filter results. I have a complex use case and am looking for some advice.
For example:
Resource 1 is tagged with the topic "Maths". Topic "Maths" has a topic label "Subject", which is tier 1
Resource 2 is tagged with the topic "Algebra". Topic "Algebra" has a topic label "Unit", which is tier 2
Resource 2 is tagged with the topic "2019". Topic "2019" has the topic label "Year", which is tier 1
Resource 2 is tagged with the topic "Calculator". Topic "Calculator" has a topic label "Question Type", which is tier 1
Resource 3 is tagged with the topic "Algebra". Topic "Algebra" has a topic label "Unit", which is tier 2
Resource 3 is tagged with the topic "2018". Topic "2018" has a topic label "Year", which is tier 1
I am trying to write a query that allows the user to get all resources that contain the provided topics.
For example:
Get me all resources tagged with the topic "2019" and topic "Algebra". This should return only Resource 2 as it has both these tags
Get me all resources that are tagged with the topic "Algebra". This should return Resource 2 and Resource 3 as they both are tagged with the topic "Algebra."
My current attempt fails to do this as it does not differntiate between the topics. My query is shown below:
query FilterBlocks($topicIds: [bigint!]) {
block(
where: {
tags: {
topic_id: { _in: $topicIds, _is_null: false }
}
}
) {
id
tags {
id
topic {
id
title
}
}
type
...
}
}
Any advice on how to go about this would be much appreciated.

If I am correct, you are querying for blocks that have a specific tag with a specific topic id.
What you expect: The blocks with just those tags and topics that are actually part of your filter.
What you get: The blocks which fulfil this filter with all their tags and topics.
You need to apply the filter to the subentities as well
query FilterBlocks($topicIds: [bigint!]) {
block(
where: {
tags: {
topic_id: { _in: $topicIds, _is_null: false }
}
}
) {
id
tags(
where: {
topic_id: { _in: $topicIds, _is_null: false }
}
) {
id
topic( where: { id: { _in: $topicIds } } ) {
id
title
}
}
type
...
}
}

Related

Query Loopring NFTs using the GraphQL "Playground"

Hello and thanks in advance for any help.
I would like to write a simple query to find out Loopring NFT (non-fungible token) data using the Loopring subgraph, given a user account number. (Note the account number is the Loopring address, similar to an Ethereum address, a hexadecimal as string type)
The subgraph playground for Loopring is here: https://thegraph.com/explorer/subgraph?id=7QP7oCLbEAjejkp7wSLTD1zbRMSiDydAmALksBB5E6i1&view=Playground
Here is my code:
query accountNFTSlotsQuery(
$skip:Int
$first:Int
$orderBy: AccountNFTSlot_orderBy
$orderDirection:OrderDirection
$where:AccountNFTSlot_filter
) {
accountNFTSlots(
skip : 0
first: 100
orderBy: createdAt
orderDirection: asc
where: {
account: "0x08F06d44D6D3e35a3790392571194d86090C863539277"
}
) {
id
account {
id
}
balance
nft {
id
nftType
nftID
mintedAt
}
}
}
The playground is returning...
{
"data": {
"accountNFTSlots": []
}
}
Which I interpret as returning NULL, or "no data found". For the address above, one can verify NFTs exist using lexplorer:
https://lexplorer.io/account/39277
Variations:
I have tried several accounts which I know have NFTs.
I have tried replacing the "account" string with an "id" in the 'where' filter thus:
where: {
id: 39277
}
Model:
I used this github repo as a model for my queries: https://github.com/fudgebucket27/Lexplorer/blob/master/Shared/Services/LoopringGraphQLService.cs

Excluding posts that are in a certain category

New to graphQL here to bear with me. I've read the docs and googled as best as I can but all I got were simplified answers and they didn't help.
I'm using WordPress as my data source.
I've been able to show posts that are in a specific category but I'm struggling to show all posts EXCEPT those in a certain category.
I want to get all posts EXCLUDING ones that are in the "Portfolio" category (ID: 10)
The top line "works" but it's only looking at the id of the post itself, not the categories it is in. The second line me what my brain thinks it should be but it doesn't work.
Please help if you can :)
query Home($page: Int) {
allWordPressPost(page: $page, perPage: 10, filter: { id: { nin: [12] }}) #paginate {
# allWordPressPost(page: $page, perPage: 10, filter: { categories.id: { nin: [12] }}) #paginate {
pageInfo {
totalPages
currentPage
}
edges {
node {
id
title
path
excerpt
categories {
id
title
path
}
}
}
}
}
Did you have a look to this repo?
I don't know if it helps, but this starter is probably better rather than the official one for this purpose!

Debezium outbox pattern | is schema is fixed with SMT/outbox table if we use debezium

Debezium with outbox pattern
Setting the context:
Using
We wanted to use schema registry to store all event schemas for different business entities
One topic can have multiple version of same schema
One topic can have entirely different schema bounded by business context. Ex customerCreated, customerPhoneUpdated, customerAddressUpdated. (Using one the subject name strtegies)
Wanted to verify if debezium supports point 2 and 3 (specially 3).
Imagine, I have two business event customerCreated and orderCreated and I wanted to store both into same topic “com.business.event”.
customerCreated
{
“id”:”244444”
“name”:”test”,
“address”: “test 123”,
“email” : “test#test.com”
}
orderCreated
{
“id”:”244444”
“value”:”1234”,
“address”: “test 123”,
“phone” : “3333”,
“deliverydate”: “10-12-19”
}
Structure of my outbox table is as per below article
https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/
Column | Type | Modifiers
--------------+------------------------+-----------
id | uuid | not null
aggregatetype | character varying(255) | not null
aggregateid | character varying(255) | not null
type | character varying(255) | not null
payload | jsonb | not null
Now when I push my business event to above table it will store customerCreated and orderCreated event into the payload column as a String/JSON. If I push this to kafka in a topic “com.business.event” using debezium connector, it will produce the below message. (Printing with schema for example)
customerCreated.json
{
"schema":
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"eventType"
},
{
"type":"string",
"optional":false,
"name":"io.debezium.data.Json",
"version":1,
"field":"payload"
}
],
"optional":false
},
"payload":
{
"eventType":"Customer Created",
"payload":"{\"id\": \"2971baea-e5a0-46cb-b1b1-273eaf88246a\", \"name\": \"jitender\", \"email\": \"test\", \"address\": \"700 \"}}"
}
}
orderCreated.json
{
"schema":
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"eventType"
},
{
"type":"string",
"optional":false,
"name":"io.debezium.data.Json",
"version":1,
"field":"payload"
}
],
"optional":false
},
"payload":
{
"eventType":"Order Created",
"payload":"{\"id\": \"2971baea-e5a0-46cb-b1b1-273eaf88246a\", \"value\": \"123\",\"deliverydate\": \"10-12-19\", \"address\": \"test\", \"phone\": \"700 \"}}"
}
}
Problem:
As you can see in above examples schema in schema registry/kafka remains same though payload contains different business entities. Now when I as a consumer goes and tries to deserialise this message, I should know that payload can contain different structure based on the business event they are generated from. In this scenerio, I am not able to utilise schema registry fully as consumer should know all the business entities in advance.
Questions :
What I wanted to do is that debezium should create two different schema’s under the same topic “com.business.event” using subject name strategy (example below).
https://karengryg.io/2018/08/18/multi-schemas-in-one-kafka-topic/
Now as a consumer when I consume the message, my consumer will read the schema id from topic message and get it from schema registry and will decode the message directly with it. After decoding I can ignore the message if I am not interested in business event. By doing this I can have different schema’s under same topic using schema registry.
Can I control the schema in kafka topic when I use debezium in conjunction with schema registry. Outbox table or outbox pattern is a must.
please take a look at https://issues.jboss.org/browse/DBZ-1297 This is probably solution to your problem and questions as it aims to unwind the opaque string into a Kafka Connect. In this case you will have the schema exposed.
Would be good if you could try it for schema per subject name strategy.

Sequelize js get count of associated model

Say for example I have a discussions table and replies table.
How do I get the count of replies for each discussion record ?
Models.course_discussions.count({
where: { 'course_id': 105 },
include: [
{model: Models.course_discussions_replies, as: 'replies'}
]
})
.then(function (discussions) {
if (!discussions) {
reply(Hapi.error.notFound());
} else {
console.log("91283901230912830812 " , discussions);
}
});
The above code is converted into the following query -
SELECT COUNT(`course_discussions`.`id`) as `count` FROM `course_discussions` LEFT OUTER JOIN `course_discussions_replies` AS `replies` ON `course_discussions`.`id` = `replies`.`discussion_id` WHERE `course_discussions`.`course_id`=105;
The above code gets me count of discussions. But how do I get the count of the replies for each discussion ?
The following sql query works, but how do I write it in the sequelize way ?
SELECT COUNT( `replies`.`discussion_id` ) AS `count`
FROM `course_discussions`
LEFT OUTER JOIN `course_discussions_replies` AS `replies` ON `course_discussions`.`id` = `replies`.`discussion_id`
WHERE `course_discussions`.`course_id` =105
If you need the discussions and the replies count maybe .replies.length should work for you.
Models.course_discussions.findAll(
where: { 'course_id': 105 },
include: [
{model: Models.course_discussions_replies, as: 'replies'}
]
})
.then(function (discussions) {
// each discussion in discussions will have a
// replies array
discussions[0].repies.length // replies for current discussion
});

MongoDB: How retrieve data that is newly constructed instead of original documents in the collection?

I have a collection in which documents are all in this format:
{"user_id": ObjectId, "book_id": ObjectId}
It represents the relationship between user and book, which is also one-to-many, that means, a user can have more than one books.
Now I got three book_id, for example:
["507f191e810c19729de860ea", "507f191e810c19729de345ez", "507f191e810c19729de860efr"]
I want to query out the users who have these three books, because the result I want is not the document in this collection, but a newly constructed array of user_id, it seems complicated and I have no idea about how to make the query, please help me.
NOTE:
The reason why I didn't use the structure like:
{"user_id": ObjectId, "book_ids": [ObjectId, ...]}
is because in my system, books increase frequently and have no limit in amount, in other words, user may read thousands of books, so I think it's better to use the traditional way to store it.
This question is not restricted by MongoDB, you can answer it in relational database thoughts.
Using a regular find you cannot get back all user_id fields who own all the book_id's because you normalized your collection (flattened it).
You can do it, if you use aggregation framework:
db.collection.aggregate([
{
$match: {
book_id: {
$in: ["507f191e810c19729de860ea",
"507f191e810c19729de345ez",
"507f191e810c19729de860efr" ]
}
}
},
{
$group: {
_id: "$user_id",
count: { $sum: 1 }
}
},
{
$match: {
count: 3
}
},
{
$group: {
_id: null,
users: { $addToSet: "$_id" }
}
}
]);
What this does is filters through the pipeline only for documents which match one of the three book_id values, then it groups by user_id and counts how many matches that user got. If they got three they pass to the next pipeline operation which groups them into an array of user_ids. This solution assumes that each 'user_id,book_id' record can only appear once in the original collection.