Lets say I have a "category" table, each category has associated data in the "data" table and it has associated data in other tables "associated" and I want to remove a category with all it's associated data.
What I'm currently doing is something like this:
getAllDataIdsFromCategory()
.then(removeAllAssociated)
.then(handleChanges)
.then(removeDatas)
.then(handleChanges)
.then(removeCategory)
.then(handleChanges);
Is there a way to chain these queries on the db-side?
my functions currently look like this:
var getAllDataIdsFromCategory = () => {
return r
.table('data')
.getAll(categoryId, { index: 'categoryId' })
.pluck('id').map(r.row('id')).run();
}
var removeAllAssociated = (_dataIds: string[]) => {
dataIds = _dataIds;
return r
.table('associated')
.getAll(dataIds, { index: 'dataId' })
.delete()
.run()
}
var removeDatas = () => {
return r
.table('data')
.getAll(dataIds)
.delete()
.run()
}
notice that I cannot use r.expr() or r.do() since I want to do queries based on the result of the previous query.
The problem with my approach is that it won't work for large amounts of "data" since I have to bring all of the ids to the client side, and doing paging for it in the client side in a loop seems like a workaround.
You can use forEach for this:
r.table('data').getAll(categoryID, {index: 'categoryId'})('id').forEach(function(id) {
return r.table('associated').getAll(id, {index: 'dataId'}).delete().merge(
r.table('data').get(id).delete())
});
Related
I'm having the dexie stores showed in the print screen below:
Dexie stores print screen
My goal is to update a dexie field row from a store without losing the rest of the data.
For example: when I edit and save the field "com_name" from the second row (key={2}) I want to update "com_name" only and not lose the rest of the properties, see first and the third row.
I already tried with collection.modify and table.update but both deleted the rest of the properties when used the code below:
dexieDB.table('company').where('dexieKey').equals('{1}')
//USING table.update
//.update(dexieRecord.dexiekey, {
// company: {
// com_name: "TOP SERVE 2"
// }
//})
.modify(
{
company:
{
com_name: TOP SERVE 2
}
}
)
.then(function (updated) {
if (updated)
console.log("Success.");
else
console.log("Nothing was updated.");
})
.catch(function (err) { console.log(err); });
Any idea how can I accomplish that?
Thanks
Alex
You where right to use Table.update or Collection.modify. They should never delete other properties than the ones specified. Can you paste a jsitor.com or jsfiddle repro of that and someone may help you pinpoint why the code doesn't work as expected.
Now that you are saying I realised that company and contact stores are created dynamically and editedRecords store has the indexes explicitly declared therefore when update company or contact store, since dexie doesn't see the indexes will overwrite. I haven't tested it yet but I suspect this is the behaviour.
See the print screen below:
Dexie stores overview
Basically I have json raw data from db and in the browser I create the stores and stores data based on it, see code below:
function createDexieTables(jsonData) { //jsonData - array, is the json from db
const stores = {};
const editedRecordsTable = 'editedRecords';
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
if (_.find(dexieDB.tables, { 'name': table }) == undefined) {
stores[table] = 'dexieKey';
}
}
});
stores[editedRecordsTable] = 'dexieKey, table';
addDataToDexie(stores, jsonData);
}
function addDataToDexie(stores, jsonData) {
dbv1 = dexieDB.version(1);
if (jsonData.length > 0) {
dbv1.stores(stores);
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
jsonPackage[table].forEach((tableRow) => {
dexieDB.table(table).add(tableRow)
.then(function () {
console.log(tableRow, ' added to dexie db.');
})
.catch(function () {
console.log(tableRow, ' already exists.');
});
});
}
});
}
}
This is the json, which I convert to object and save to dexie in the value column and the key si "dexieKey":
[
{
"company": [
{
"dexieKey": "{1}",
"company": {
"com_pk": 1,
"com_name": "CloudFire",
"com_city": "Round Rock",
"serverLastEdit": [
{
"com_pk": "2021-06-02T11:30:24.774Z"
},
{
"com_name": "2021-06-02T11:30:24.774Z"
},
{
"com_city": "2021-06-02T11:30:24.774Z"
}
],
"userLastEdit": []
}
}
]
}
]
Any idea why indexes were not populated when generating them dynamically?
Given the JSON data, i understand what's going wrong.
Instead of passing the following to update():
{
company:
{
com_name: "TOP SERVE 2"
}
}
You probably meant to pass this:
{
"company.com_name": "TOP SERVE 2"
}
Another hint is to do the add within an rw transaction, or even better if you can use bulkAdd() instead to optimize the performance.
I need to run multiple graphQL queries within a component and within the gatsby-node.js file. (Because Prismic is limited to 20 entries per answer...🙄)
I tried the following, just to see if I could create the graphql loop in the default function:
export default () => {
async function allPosts() {
let data
await graphql(`
query allDitherImages {
prismic {
allProjects(sortBy: meta_firstPublicationDate_DESC) {
totalCount
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
node {
cover_image
cover_imageSharp {
name
}
}
}
}
}
}
`).then(initialRes => {
data = initialRes
})
return data
}
allPosts().then(result => {
console.log(result)
})
return null
}
But then Gatsby tells me that Gatsby related 'graphql' calls are supposed to only be evaluated at compile time, and then compiled away. Unfortunately, something went wrong and the query was left in the compiled code.
How can I run multiple graphql queries?
Thank you in advance :)
Michael
The gatsby-source-prismic-graphql package will create pages for all of your Prismic items (more than just the first 20), as it iterates over all items under the hood, so I'd advise looking into using that if you are looking to generate pages for all of those items.
But if you need to get all items and pass them in the pageContext or something, you'll need to do the recursion yourself in the gatsby-node.
In the gatsby-node, after you have defined the query, you can use something like this to iterate over the results and push to an array.
let documents = [];
async function getAllDocumentsRecursively (query, prop, endCursor = '') {
const results = await graphql(query, { after: endCursor })
const hasNextPage = results.data.prismic[prop].pageInfo.hasNextPage
endCursor = results.data.prismic[prop].pageInfo.endCursor
results.data.prismic[prop].edges.forEach(({node}) => {
documents.push(node)
});
if (hasNextPage) {
await getAllDocumentsRecursively(query, 'allDitherImages ', endCursor)
}
}
await getAllDocumentsRecursively(documentsQuery, 'allDitherImages ');
Then in your createPage, pass the array into the context:
createPage({
path: `/`+ node._meta.uid,
component: allDitherTempate,
context: {
documents: documents
}
})
I've been playing around with resolvers in graphql and need what's seemingly a simple query, but I can't figure it out.
I want to query a table and get results in something like this:
SELECT hero_id, count(id) FROM "Build"
GROUP BY hero_id
ORDER BY hero_id
How do I write the resolver to return the count of rows by id on a table?
I thought the Table.findAndCountAll() would return results I'm looking for.
const buildCount = {
type: BuildCountType,
resolve(parent, args){
return Build.findAndCountAll().then(result => {
console.log(result)
return {
count: result.rows
}
})
}
}
Thanks,
StuckAndConfused ;)
I am hitting the following problem: Suppose that I have the following structure:
{
"id": 1,
"data": {
"arr": [{"text":"item1"}]
}
}
And the following query:
r.db('test').table('test').get(1).update(function (item) {
return {
data: {
arr: item('data')('arr').map(function (row) {
return r.branch(
row('text').eq('item1'),
row.merge({updated:true}),
row
)
})
}
}
})
I am listening for changes in this specific array only, and when the item is updated both create and delete events are emitted. I really need to receive an update event, e.g. old_val is not null and new_val is not null.
Thanks in advance guys
After all, I decided to drop the embedded array and use table joins, this avoids all possible hacks.
You can use something like this
r.db('test').table('test')('data')('arr').changes()
.filter(function(doc) {
return doc('new_val').ne(null).and(doc('old_val').ne(null))
})
I'll only show update to array. If you need to get access to other document field, try this:
r.db('test').table('test').changes()
.filter(function(doc) {
return doc('new_val')('data')('arr').ne(null).and(doc('old_val')('data')('arr').ne(null))
})
Rethinkdb docs has this example to improve getAll/contains queries with a secondary index:
// Create the index
r.table("users").indexCreate("userEquipment", function(user) {
return user("equipment").map(function(equipment) {
return [ user("id"), equipment ];
});
}, {multi: true}).run(conn, callback);
// Query equivalent to:
// r.table("users").getAll(1).filter(function (user) {
// return user("equipment").contains("tent");
// });
r.table("users").getAll([1, "tent"], {index: "userEquipment"}).distinct().run(conn, callback);
My questions is if there's a way to do the same but for querying with multiple tags. What would be the equivalent to make this query possible with a secondary index?
r.table("users").getAll(1).filter(function (user) {
return user("equipment").contains("tent", "tent2");
});
Probably we can do this
r.table("users").getAll([1, "tent"]).filter(function (user) {
return user("equipment").contains("tent2");
});
So build a multi index as you did, and try to getAll first, so that part is efficient with index, then filter to continue ensure that equipment contains array we want.