Knex JS - update & select in the same query (simultaneously) - javascript

Using Knex JS - Is it possible to get all elements from the row being updated, I would like update and select to be done in a single query. (currently update only returns the id of the row being updated).
let query = await knex('items').select('id', 'customerId', 'itemId').where('id', id).update({ inactive: true })
Thanks!

If using postgres, then use .returning()
const query: any = await knex('items')
.returning('id', 'customerId', 'itemId')
.where('id', id)
.update({ inactive: true });
here is the knex documentation
https://knexjs.org/#Builder-returning

Related

Prisma - Optimistic Update using LastUpdated field, is it possible to express with Prisma's safe query builder syntax?

I am working with a PostgreSQL database using Prisma. I have a bulk update command which I want to fail if any of the records have changed since my last read.
My schema:
model OrderItem {
id String #id #default(uuid()) #db.Uuid
quantity Int
lastUpdated DateTime #updatedAt #map("last_updated")
##map("order_item")
}
I have written a query which works, but I built the query manually rather than using Prisma's safe query builder tools.
My query:
type OrderItemType = {
id: string;
quantity: number;
lastUpdated: Date;
}
type OrderItemUpdateDataType = {
quantity: number;
}
const updateByIds = async (
orderItemIdLastUpdatedTuples: ([OrderItemType['id'], OrderItemType['lastUpdated']])[],
orderItemUpdateData: OrderItemUpdateDataType,
) => {
// Optimistic concurrency - try updating based on last known "last updated" state. If mismatch, fail.
await prisma.$transaction(async (prisma) => {
// TODO: Prefer prisma.$queryRaw. Prisma.join() works on id[], but not on [id, lastUpdated][]
const idLastUpdatedPairs = orderItemIdLastUpdatedTuples
.map(([id, lastUpdated]) => `(uuid('${id}'), '${lastUpdated.toISOString()}')`)
.join(', ');
const query = `SELECT * FROM order_item WHERE (id, last_updated) in ( ${idLastUpdatedPairs} )`;
const items = await prisma.$queryRawUnsafe<OrderItem[]>(query);
// If query doesn't match expected update count then another query has outraced and updated since last read.
const itemIds = orderItemIdLastUpdatedTuples.map(([id]) => id);
if (items.length !== orderItemIdLastUpdatedTuples.length) {
throw new ConcurrentUpdateError(`Order Items ${itemIds.join(', ')} were stale. Failed to update.`);
}
await prisma.orderItem.updateMany({
where: { id: { in: itemIds } },
data: orderItemUpdateData,
});
});
};
This function wants to update a set of items. It accepts a list of tuples - id/lastUpdated pairs. It starts an explicit transaction, then performs an unsafe SELECT query to confirm the items to affect haven't been updated, then updates. This is following the guidance of Prisma's docs here - https://www.prisma.io/docs/concepts/components/prisma-client/transactions#interactive-transactions-in-preview
I was hoping to achieve the same results using prisma.$queryRaw rather than prisma.$queryRawUnsafe or even using implicit transactions rather than an explicit transaction wrapper. I wasn't able to find a syntax for expressing "where in tuple" using either of these approaches, though.
I am able to express what I want using implicit transactions when updating a single record. An example here would look like:
const { count } = await prisma.orderItem.updateMany({
where: { id, lastUpdated },
data: orderItemUpdateData,
});
and when using an explicit, safe query I stumbled on joining the array of tuples properly.
From the Prisma documentation, https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#tagged-template-helpers, there exists a Prisma.join command (which happens implicitly when using their tagged template helper syntax) but I wasn't able to generate a valid output when feeding it an array of tuples.
Did I miss anything? Does Prisma support joining a tuple using their safe query template syntax?

Can you build a query in prisma without executing it?

I have a find method in my api that takes these parameters
-limit (optional)
-select (optional)
-sort (optional)
-skip (optional)
In MongoDB you can build a query like this :
let query = model.find(query);
if(limit) {
query.limit(limit)
}
if(skip) {
query.skip(skip)
}
// ....
let result = await query.exec();
Is there a similar option in Prisma ?
I am not Prisma user, but seems like you can build config parameters beforehand like
let query = {
skip: skip,
take: limit
};
prisma.model.findMany(query)

Problem when add data in Subcollection Firebase v9

await addDoc(collection(db, 'users', idDoc, 'notes'), {
title: noteTitle,
body: 'comentario por defecto.',
timestamp: serverTimestamp(),
});
When I trying to add data in my sub collection 'notes'. Appear this mistake, I don't know what is happening because I using the same code reference in Firebase v9 Documentation.
Extra Note: idDoc returns me: YYwcNWMfznuwAB8eN0sU
you use await first see async function is nesscesssry
addDoc(collection(db, 'Institute', 'Private', 'College'), { name:"tunio" })
this is working for me
It seems you were in the right direction but I would recommend checking how to reference subcollections and then using that reference to write data into it.
It won't hurt to check your imports and dependencies as well.
import { doc } from "firebase/firestore";
const messageRef = doc(db, "rooms", "roomA", "messages", "message1");
This translated to your project would be:
const notesRef = doc(db, 'users', idDoc, 'notes');
Next, you need to check the Add a document section as well. The code you are using as a reference applied to your app would create a new note with an auto-generated id. In the reference, "cities" would correspond to your "notes" reference.
Finally, if you substitute this, it would look like this:
const noteRef = await addDoc(collection(db, notesRef), {
title: noteTitle,
body: 'comentario por defecto.',
timestamp: serverTimestamp() // You also had an extra coma here
});
console.log("Note written with ID: ", noteRef.id);
The console log is optional
try this one for add subcollections in firebase v9
`function uploadData() {
var id = 'id_' + Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); //create id for uniqness
setDoc(doc(db, "Institute", `college`, `city`, `${id}`), {
Name: "CAted college"
})}`
//if you not use id set primary as name then no need to use id only write "name" of sugeesttion that unique for data base instead of id

Update mongoDB updating in forEach not working

I have a Node backend server, connected to a MongoDB database. Here I have a patients collections containing patients object. I'm trying to update an attribute called position on each object.
I have started by retrieving the documents from MongoDB:
const patientsToChange = await Patient.find()
Then I'm trying to update some attributes in the array by iteration over the array.
patientsToChange.forEach(function (patient) {
patient.queuePosition = parseInt(patient.queuePosition) + 1
console.log(patient._id)
let updatedPatient = patient.update({ _id: patient._id }, patient)
})
What am I missing here?
Is it even possible to update in a forEach loop?
instead of patient.update you should use Patient.update. Also it is better to use $inc for incrementing one field:
Patient.updateOne({ _id: patient._id }, { $inc: { queuePosition }} )

Firestore: Query by item in array of document

I have 2 collections "photos" and "users" and each document in "users" has one or more photo IDs with an array.
photos > 5528c46b > name: "Photo1"
a1e820eb > name: "Photo2"
32d410a7 > name: "Photo3"
users > acd02b1d > name: "John", photos: ["5528c46b"]
67f60ad3 > name: "Tom", photos: ["5528c46b", "32d410a7"]
7332ec75 > name: "Sara", photos: ["a1e820eb"]
9f4edcc1 > name: "Anna", photos: ["32d410a7"]
I want to get all users who have one or more specific photo IDs.
Are there any ways to do that?
See Henry's answer, as we've no made Array Contains queries available.
Unfortunately not yet, although it's on our roadmap.
In the meantime, you'll need to use a map instead, in the form of:
photos: {
id1: true
id2: true
}
Now you can find all users with id1 by filtering by photos.id1 == true.
Read more about querying such sets in the Firebase documentation.
Added 'array-contains' query operator for use with .where() to find documents where an array field contains a specific element.
https://firebase.google.com/support/release-notes/js 5.3.0
Update: also available in #google-cloud/firestore: https://github.com/googleapis/nodejs-firestore/releases/tag/v0.16.0
Update 2 https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
Update 3 now available in Admin Node.js SDK v6.0.0 https://github.com/firebase/firebase-admin-node/releases
Here is a bit of expansion on the answer as some seem to be confused about having to make indexes for each key, Firestore already indexes your data for simple queries thus you can do a simple query like
documentReference.where('param','==','value').onSnapshot(...)
but you can not do a compound query unless you index your data for those parameters. So you would need indexes to be able to do something like this:
documentReference.where('param','==','value').where(..otherparams...).onSnapshot(...)
So as long as you need the photos for an id you can save them as
usersCollection : (a collection)
uidA: (a document)
photoField: (a field value that is a map or object)
fieldID1 : true (a property of the photoField)
fieldID2 : true (a property of the photoField)
etc ...
and you can simply query user(s) that have, let's say, fieldID1 in their photoField without needing to form any index and like query below.
firestore.doc('usersCollection/uidA').where('photoField.fieldID1','==',true).onSnapshot(...)
Firestore has now added an 'in' query as of November 2019.
According to the announcement article:
With the in query, you can query a specific field for multiple values
(up to 10) in a single query. You do this by passing a list containing
all the values you want to search for, and Cloud Firestore will match
any document whose field equals one of those values.
With Firebase Version 9 (Dec, 2021 Update):
You can use "array-contains" with one single photo document ID in the "while()" to get all users who have it:
import {
query,
collection,
where,
getDocs
} from "firebase/firestore";
// Here
const q = query(
collection(db, "users"),
where("photos", "array-contains", "5528c46b")
);
// Here
const usersDocsSnap = await getDocs(q);
usersDocsSnap .forEach((doc) => {
console.log(doc.data()); // "John's doc", "Tom's doc"
});
You can alse use "array-contains-any" with one or more photo document IDs with an array in the "while()" to get more corresponding users:
import {
query,
collection,
where,
getDocs
} from "firebase/firestore";
// Here
const q = query(
collection(db, "users"),
where("photos", "array-contains-any", ["5528c46b", "a1e820eb"])
);
// Here
const usersDocsSnap = await getDocs(q);
usersDocsSnap .forEach((doc) => {
console.log(doc.data()); // "John's doc", "Tom's doc", "Sara's doc"
});

Categories

Resources