updating an array of nested documents rethinkdb - rethinkdb

I have a document schema like this:
{
"name":"",
"type":"",
"posts":[
{
"url":"",
"content":"",
...
},
{
"url":"",
"content":"",
...
}
...
]
}...
I forgot to create id's for each post on insertion in database. So i'm trying to create a query for that:
r.db('test').table('crawlerNovels').filter(function (x){
return x.keys().contains('chapters')
}).map(function (x){
return x('chapters')
}).map(
function(x){
return x.merge({id:r.uuid()})
}
)
instead this query return all posts with an id but doesn't actually update in the database. I tried using a forEach instead of a map function at the end this doesn't work

After lots of tweaking and frustration i figured it out:
r.db('test').table('crawlerNovels').filter(function (x){
return x.keys().contains('chapters')
}).update(function(novel){
return {"chapters":novel('chapters').map(
function(chapter){
return chapter.merge({"id":r.uuid()})
})}
},{nonAtomic:true})

Related

Multiple graphql queries in Gatsby component

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
}
})

Laravel Eloquent getting value from previous relation/pivot

I have a bunch of results coming from eager loading through many to many relations. I need to filter one thing, I have this output :
"id_stats":32,
"n_stats":"Mastery",
"image_stats":null,
"pivot":{
"id_equipement":11,
"id_stats":32,
"weight":"235",
"rand-elem":"3"
},
"elements":[
{
"id_elements":2,
"n_elements":"Feu",
"pivot":{
"id_stats":32,
"id_elements":2,
"id_equipement":15
}
},
{
"id_elements":3,
"n_elements":"Eau",
"pivot":{
"id_stats":32,
"id_elements":3,
"id_equipement":13
}
}
]
I must filter the equipement on pivot(parent).id_equipement = elements.id_equipement otherwise I will have the result of the whole table. I can either filter my result like this. I already tried to add an inner join in my belongsToMany relation but it didn't help!
Here is parts of my code:
EncyclopedieModel.php
public function stats(){
return $this->belongsToMany(StatsModel::class, 'equipement_stats', 'id_equipement','id_stats')
->withPivot('weight')->withPivot('random');
}
StatsModel.php
public function elements(){
return $this->belongsToMany(ElementModel::class, 'stuff_equipement_stats_elements', 'id_stats', 'id_elements')
->withPivot('id_equipement');
}
Thanks!

ReQL Updating object inside an embedded array emits "create" and "delete" events when listening to changes

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))
})

How to use secondary indexes for a "contains" query

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.

RethinkDB index query with several .contains()

I have the following query that works fine but is slow, however I can't figure out how to index it properly:
r.db('my_db')
.table('messages')
.filter({ community_id : community.id})
.filter(function(row){
return row('mentions').contains(user.id);
})
.filter(function(row){
return row('channels').contains(channel.id);
})
.orderBy(r.desc('created_at'))
.skip(0)
.limit(50);
I tried with the following index (using Thinky.js):
Model.ensureIndex("user_mentions", function(message){
return message("mentions").map(function(user_id){
return message("channels").map(function(channel_id){
return [
message("community_id"),
message("mentions").contains(user_id),
message("channels").contains(channel_id),
message('created_at')
];
});
});
}, {multi: true});
And then to query it I've tried this:
r.db('my_db')
.table('messages')
.between(
[community.id, user.id, channel.id, r.minval],
[community.id, data.user.id, channel.id, r.maxval],
{ index : 'user_mentions' }
)
.orderBy({index:r.desc("user_mentions")})
.skip(0)
.limit(50);
The messages table looks like:
id | community_id | mentions (array of user_ids) | channels (array of channel_ids) | created_at
But I end up getting zero results.
I greatly appreciate any suggestions!
I think this index will make the between query you wrote above work:
.indexCreate(function(message) {
return message('channels').concatMap(function(channel) {
return message('mentions').map(function(mention) {
return [
message('community_id'),
mention,
channel,
message('created_at')
];
});
});
}, {multi: true});

Resources