How check if has minimum one row in Select - PostgreSQL/Flutter - postgresql

I have 3 tables (in Supabase -> PostgreSQL):
posts(
id_post INT,
id_user INT NOT NULL,
PRIMARY KEY(id_post),
FOREIGN KEY(id_user) REFERENCES users(id_user)
);
users(
id_user INT,
PRIMARY KEY(id_user),
UNIQUE(pseudo_user),
);
follows(
id_following INT,
id_follower INT,
PRIMARY KEY(id_following , id_follower ),
FOREIGN KEY(id_following ) REFERENCES users(id_user),
FOREIGN KEY(id_follower ) REFERENCES users(id_user)
);
My query for the moment is supabase.from('posts').select('*, users(*)').execute();
The result will be
{[
id_post : 1,
users : {id_user: 1}
]}
But I want to check if a row exist in follows where 'id_follower' = 1 and 'id_following' = the user_id of the post
So I want:
{[
id_post : 1,
users : {id_user: 1, isFollowed: 1}
]}
If the current user follow the user of the post, otherwise it will be 0.

You can use match for filtering plus the count option.
const { data, count } = supabase
.from('follows')
.select('*', { count: 'exact' })
.match({ id_user: 1, id_following: user_id })
I didn't find documentation for Flutter, btw I think the syntax is similar of the javascript one.
https://supabase.com/docs/reference/javascript/filter#filter-embedded-resources
https://supabase.com/docs/reference/javascript/select#querying-with-count-option

Related

Return nested data from recursive query

We have a list of recipes (recipe_id) and ingredients (ingredient_id). Every recipe can become an ingredient of another recipe and that child recipe can then hold more second level child recipes and so on. I need a recursive query that takes a recipe id (or an array of ids - how I have it setup now) and returns a NESTED table or array of all the ingredients of the main recipes and any child recipes.
We're using Postgresql / Supabase / PostgREST.
So far I've been able to create the recursive query as a RPC function that returns a table using UNION ALL. This gives me a flat table back and I can't definitively trace back an ingredient to a specific parent recipe (because the same recipe can be called as a child in multiple parent recipes). Not sure where to go from here? The only other option I've figured out so far is to have my API endpoint query each level one at a time, but it generates a lot of network requests =(
DESIRED OUTPUT
Super flexible on format, but it would be nice if I could get all the child components as a nested array like so:
[
{ id: 1,
recipe_id: 22,
item_id: 9,
item: "Croissant Dough",
...,
components: [
{ id: 2,
recipe_id: 1,
item_id: 33,
item: "Butter,
...,
components: []
},
{ id: 3,
recipe_id: 1,
item_id: 71,
item: "Wheat Flour",
...,
components: []
}
]
},
{ id: 1,
recipe_id: 29,
item_id: 4,
item: "Almond Filling",
...,
components: [
{ id: 2,
recipe_id: 29,
item_id: 16,
item: "Almond Meal,
...,
components: []
},
{ id: 3,
recipe_id: 29,
item_id: 42,
item: "Pastry Cream",
...,
components: [
{ id: 7,
recipe_id: 42,
item_id: 22,
item: "Egg Yolks",
...,
components: []
]
}
]
},
]
CURRENT RPC FUNCTION
CREATE or REPLACE FUNCTION recipe_components_recursive (recipeids text)
RETURNS TABLE (id int8, recipe_id int8, item_id int8, quantity numeric, unit_id int8, recipe_order int4, item text, visible bool, recipe bool, "unitName" varchar, "unitAbbreviation" varchar, "conversionFactor" float4, "metricUnit" int8, batch bool)
LANGUAGE plpgsql
AS $$
DECLARE
transformedjson int[] := recipeids;
BEGIN
RETURN QUERY
WITH RECURSIVE recipe_components_rec_query AS (
SELECT *
FROM recipe_components_items
WHERE recipe_components_items.recipe_id = ANY (transformedjson)
UNION ALL
SELECT o.id, o.recipe_id, o.item_id, o.quantity, o.unit_id, o.recipe_order, o.item, o.visible, o.recipe, o."unitName", o."unitAbbreviation", o."conversionFactor", o."metricUnit", o.batch
FROM recipe_components_items o
INNER JOIN recipe_components_rec_query n ON n.item_id = o.recipe_id AND n.recipe = true
) SELECT *
FROM recipe_components_rec_query;
END $$;

DynamoDB Error: "Query key condition not supported"

I am querying data from a database in aws dynamodb and experiencing an error message on the KeyConditionExpression.
I am querying for "dominant_temporality" and "dt". These make up my composite partition key - dt is unique for each row and my sort key.
The code I'm running:
var params = {
TableName : "deardiary",
KeyConditionExpression: "#d = :dominant_temporality and dt between :minDate and :maxDate",
ExpressionAttributeNames: {
"#d" : "temporality"
},
ExpressionAttributeValues: { // the query values
":dominant_temporality": {S: "present"},
":minDate": {N: new Date("October 8, 2018").valueOf().toString()},
":maxDate": {N: new Date("October 9, 2018").valueOf().toString()}
}
};
Check if you are using BETWEEN on HASH which is not allowed - you can use only EQ for HASH or begins_with for range key.

MongoDB: how to insert document without repeat

Suppose I already have some data in database:
{
id: 001,
title: "title_1"
}
{
id: 002,
title: "title_2"
}
{
id: 003,
title: "title_3"
}
then I want to insert some new documents:
{
id: 003 // id repeat
title: "title_4"
}
{
id: 004
title: "title_5"
}
but I don't want to insert the { id:003 } item, because some guy in the database already has the same id.
So, how can I let the MongoDB ignore the repeat value(with specified key) item when I insert new data?
For this you have to create unique index on id. You have to try like this:
db.collection.ensureIndex( { id: 1 }, { unique: true } )
I think you could use a Unique Index
Apart from putting this as unique index as it was suggested earlier, you can just insert them with a different key. Instead of id key as you already have, you can insert them with unique primary key _id (you can use your own unique _id field if you want so http://docs.mongodb.org/manual/core/document/#the-id-field)

Golang/mgo: How can I ask MongoDB to use current time in a field?

I have this struct that matches the types of a MongoDB collection I'm using:
type AppInstance struct {
Id bson.ObjectId "_id,omitempty"
Url string
Priority int
LastSeen string
}
I want the LastSeen field to hold the time of the last interaction with that particular app. So, the app registers itself setting current time (as a string).
What I would like is Mongo to dynamically set its own current time into that field when it inserts, just like MySQL's NOW() function would do.
I have this helper function:
func mongoNow() bson.JavaScript {
return bson.JavaScript{Code:
"return (new Date()).ISODate('YYYY-MM-DD hh:mm:ss');"}
}
And I tried this:
c := mongoSession.DB("myapp").C("instances")
rand.Seed(time.Now().UnixNano())
err := c.Insert(
struct{Id, Serial, Priority, Url, LastSeen interface{}}{
Id: bson.NewObjectId(),
Url: getInformedHost() + ":" + getRunningPortString(),
Priority: rand.Int(),
LastSeen: mongoNow() }
)
checkError(err, "Could not register on MongoDB server.", 3)
the LastSeen field gets stored as a script instead of evaluated:
[_id] => MongoId Object (
[$id] => 502d6f984eaead30a134fa10
)
[id] => MongoId Object (
[$id] => 502d6f98aa443e0ffd000001
)
[priority] => 1694546828
[url] => 127.0.0.1:8080
[lastseen] => MongoCode Object (
[code] => (new Date()).ISODate('YYYY-MM-DD hh:mm:ss')
[scope] => Array (
)
)
So, I think there are to questions:
First, how can I insert the current time?
Second, how can I get some javascript evaluated instead of inserted?
The answer to the second one could be enough to answer the first one, but it might as well not be.
Don't store time as string. mgo supports time.Time which is like a Date object in Javascript:
type Event struct {
Id bson.ObjectId "_id,omitempty"
Which string
Date time.Time
}
Insert an event that happened now:
e := Event{
Which: "first event",
Date: time.Now(),
}
c.Insert(e)
In Mongo 2.6 you can do it natively with $currentDate operator.
db.users.update( { _id: 1 }, {
$currentDate: {
lastModified: true,
lastModifiedTS: { $type: "timestamp" }
},
$set: { status: "D" }
})

How to get last inserted id using the JS api?

Using the javascript api for MongoDB, how do you get the ID of the last inserted object? i.e.
obj = {a: 1, b: 2};
db.foo.insert(obj);
How do I get the ID for obj?
The people on #mongodb were helpful. The JS API doesn't currently support this, but you can use your own id. To generate a "normal" id, do _id: new ObjectId(). So the example in my question would be:
id = new ObjectId();
obj = {a: 1, b: 2, _id: id};
db.foo.insert(obj);
If you run
db.collection("venues").insert( {name: "test3", FSid: "test3"}, function( err, ret) {
console.log( ret )
})
it returns
{ result: { ok: 1, n: 1 },
ops: [ { name: 'test3', FSid: 'test3', _id: 57cb0a1162cecfe636df6fc1 } ],
insertedCount: 1,
insertedIds: [ 57cb0a1162cecfe636df6fc1 ] }
So you can get your ids along with all inserted objects through:
ret.ops[0]._id
or straight
ret.insertedIds[0]
Now,the mongo native js api supports this. You can get the last id like this:
collection.insert(line, {w : 1}, function(err, inserted) {
inserted[0]._id
}
insert sets the _id property on the inserted object, but it looks like you have to wait for the object to return. The best documentation I've found for this is (unfortunately) in the source code:
https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js
If you insert the data like this:
var temptodo = new User({
title: data.todo.text,
email: socket.handshake.email,
created_at: Date.now(),
completed: false,
sid: socket.handshake.sid
});
temptodo.save( function(error, User){
console.log("this is the id for the new todo. "+User._id);
console.log('Todo saved in database with sid: '+socket.handshake.sid);
});
Then you can grab the _id like this: console.log("this is the id for the new todo. "+User._id);