RethinkDB - delete a nested object - rethinkdb

I am trying to delete a nested object, but instead of disappearing it is being replaced by an empty object.
Here's the structure of my documents:
[
{
"id": "0" ,
"name": "Employee 1" ,
"schedules": [
{"Weekdays": "yes"},
{"Weekends": "no"}
]
} ,
{
"id": "1" ,
"name": "Employee 2" ,
"schedules": [
{"Weekdays": "no"},
{"Weekends": "yes"}
]
}
]
Let's say I want to delete "Weekends". Here's my code:
r.db('shank').table('teachers').replace(r.row.without({'schedules': 'Weekends'})).run(connection, function(err, result) {
if (err) throw err;
;
//confirmation stuff
});
});
Now if I look at my table, the documents have this:
"schedules": [
{"Weekdays": "yes"},
{}
]
I also tried changing it to follow the syntax described here, by making it:
r.row.without({'schedules': {'Weekends'}})
but I got an error of an unexpected token '}'. Any idea what's up?

This should work:
r.db('test').table('test').get('0').update(function(doc) {
return doc.merge({
schedules: doc("schedules").filter(function(schedule) {
return schedule.hasFields('Weekends').not()
})
})
})
The field schedules is an array, is that expected? Is there a reason why it's not just an object with two fields Weekends and Weekdays? That would make things way easier.

Your last one is close to what worked for me, just need to add a true to the nested JSON object:
r.row.without({'schedules': {'Weekends': true}})

Related

HTTP CORS on Graphql server won't insert

I'm working on this project where I have 3 "tables". 2 of them are independent and one is M:M relationship.
However, my database was working fine until I realized it could not liaise the 2 independent table in the 3rd one, so I decided to change up the ids with "_" and make it work like that. However, it keeps returning me the 400 Error and I cant seem to figure out why.
{
"students": [
{
"id": 3021,
"nume": "Name",
"prenume": "Surname",
"an": 3,
"departament": "1"
}
],
"exams": [
{
"id": 1,
"subiect": "Subject",
"data_examen": "02/06/2022 10:00",
"profesor": {
"nume": "Name Surname"
}
}
],
"listexams": [
{
"id":1,
"exam_id":1,
"student_id":3021
}
]
}
Insertion code:
`function send()
{
dategraph.forEach((graph) => {
deInserat={ examenId:graph.examId,studentId:graph.studentId};
obiectInterogare={query:`mutation adaugare($examenId:Int!,$studentId:Int!)
{createListaexamene(examId:$examenId, studentId:$studentId) {id examId studentId}}`,
variables:JSON.stringify(deInserat)}
textInterogare=JSON.stringify(obiectInterogare)
configurari={url:"http://localhost:3000/",
type:"POST",
data:textInterogare,
contentType:"application/json",
success:procesareRaspunsql,
error: (error) =>
{
console.log('Error', error);
}
}
$.ajax(configurari);
});
}`
It's taking the variables from another place but that is working just fine (because it worked prior to changing the fields) but it won't now. Any ideas what it could be?
The error that gets thrown out is
This might help somebody. Beware of the implicit GraphQL schema. The reason why it kept throwing out 400 Error is because I had the M:M relationship keys defined as "int!" instead of "ID!"
As I stated in the question, I knew it's something in the query/database. Thanks to the expert who downvoted it

Match keys with sibling object JSONATA

I have an JSON object with the structure below. When looping over key_two I want to create a new object that I will return. The returned object should contain a title with the value from key_one's name where the id of key_one matches the current looped over node from key_two.
Both objects contain other keys that also will be included but the first step I can't figure out is how to grab data from a sibling object while looping and match it to the current value.
{
"key_one": [
{
"name": "some_cool_title",
"id": "value_one",
...
}
],
"key_two": [
{
"node": "value_one",
...
}
],
}
This is a good example of a 'join' operation (in SQL terms). JSONata supports this in a path expression. See https://docs.jsonata.org/path-operators#-context-variable-binding
So in your example, you could write:
key_one#$k1.key_two[node = $k1.id].{
"title": $k1.name
}
You can then add extra fields into the resulting object by referencing items from either of the original objects. E.g.:
key_one#$k1.key_two[node = $k1.id].{
"title": $k1.name,
"other_one": $k1.other_data,
"other_two": other_data
}
See https://try.jsonata.org/--2aRZvSL
I seem to have found a solution for this.
[key_two].$filter($$.key_one, function($v, $k){
$v.id = node
}).{"title": name ? name : id}
Gives:
[
{
"title": "value_one"
},
{
"title": "value_two"
},
{
"title": "value_three"
}
]
Leaving this here if someone have a similar issue in the future.

Error while accessing nested JSON object

This is a sample row in my RethinkDB table.
{
"a1": "val1" ,
"a2": "val2" ,
"a3": "val3" ,
"a4": "val4" ,
"part": [
{
"id": "reql" ,
"position": "student"
} ,
{
"id": "sdsadda" ,
"position": "officer"
}
] ,
"a5": "val5"
}
I want to access a nested json object but I get the error e: Cannot perform bracket on a non-object non-sequence "string"
I need the entire row in the output for rows matching id to "reql"
This is my query
r.db('dbname').table('tablename').filter(r.row('part').contains(function(product) {
return product('id').eq("reql");
}))
This query worked before .It doesn't right now.
You'd get that error if you'd somehow ended up with an element in your part array that's a string instead of an object. Try running .filter(r.row('part').contains(function(product) { return product.typeOf().ne('OBJECT'); }), that should return all the rows that have a string in the part array.
Regarding your comment #Puja, I think this should do it for you:
r.db('dbname').table('tablename').filter(function(d){
d("part").typeOf().eq("ARRAY");
}).filter(r.row('part').contains(function(d) {
return d('id').eq("reql");
}))
Although, this is less efficient than #mlucy's answer, and you should definitely just do the one pass over your dataset to clean it up by fixing all the documents where part: STRING.

How can I modify array fields in place?

Let's say I have this object:
{
"id": "1a48c847-4fee-4968-8cfd-5f8369c01f64" ,
"sections": [
{
"id": 0 ,
"title": "s1"
} ,
{
"id": 1 ,
"title": "s2"
} ,
{
"id": 2 ,
"title": "s3"
}
]
}
How can I directly change 2nd title "s2" to other value? without loading the object and save again? Thanks.
Update plus the changeAt term:
r.table('blog').get("1a48c847-4fee-4968-8cfd-5f8369c01f64").update(function(row){
return {
sections: row('sections').changeAt(1,
row('sections')(1).merge({title: "s2-modified"}))
}
}
The above is good if you already know the index of the item you want to change. If you need to find the index, then update it, you can use the .offsetsOf command to look up the index of the element you want:
r.table('table').get("1a48c847-4fee-4968-8cfd-5f8369c01f64").update(function(row){
return row('sections').offsetsOf(function(x){
return x('title').eq('s2')
})(0).do(function(index){
return {
sections: row('sections').changeAt(index,
row('sections')(index).merge({title: "s2-modified"}))
}
})
})
Edit: modified answer to use changeAt

How to use two conditon in one array?

I have a list of task stored in Mongo, like below
{
"name": "task1",
"requiredOS": [
{
"name": "linux",
"version": [
"6.0"
]
},
{
"name": "windows",
"version": [
"2008",
"2008R2"
]
}
],
"requiredSW": [
{
"name": "MySQL",
"version": [
"1.0"
]
}
]
}
My purpose is to filter the task by OS and Software, for example the user give me below filter condition
{
"keyword": [
{
"OS": [
{
"name": "linux",
"version": [
"6.0"
]
},
{
"name": "windows",
"version": [
"2008"
]
}
]
},
{
"SW": [ ]
}
]
}
I need filter out all the task can both running on the windows2008 and Linux 6.0 by searching the "requiredOS" and "requiredSW" filed. As you seen, the search condition is an array (the "OS" part). I have a trouble when use an array as search condition. I expect the query to return me a list of Task which satisfy the condition.
A challenging thing is that I need to integrate the query in to spring-data using #Query. so the query must be parameterized
can anyone give me a hand ?
I have tried a query but return nothing. my purpose is to use $all to combine two condition together then use $elemMatch to search the "requiredOS" field
{"requiredOS":{"$elemMatch":{"$all":[{"name":"linux","version":"5.0"},{"name":"windows","version":"2008"}]}}}
If I understood correctly what you are trying, you need to use $elemMatch operator:
http://docs.mongodb.org/manual/reference/operator/query/elemMatch/#op._S_elemMatch
Taking your example, the query should be like:
#Query("{'requiredOS':{$elemMatch:{name:'linux', version:'7.0'},$elemMatch:{name:'windows', version:'2008'}}}")
It match the document you provided.
You basically seem to need to translate your "parameters" into a query form that produces results, rather than passing them straight though. Here is an example "translation" where the "empty" array is considered to match "anything".
Also the other conditions do not "literally" go straight through. The reason for this is that in that form MongoDB considers it to mean an "exact match". So what you want is a combination of the $elemMatch operator for multiple array conditions, and the $and operator which combines the conditions on the same property element.
This is a bit longer than $all but essentially because that operator is a "shortened" form of $and as $in is to $or:
db.collection.find({
"$and": [
{
"requiredOS": {
"$elemMatch": {
"name": "linux",
"version": "6.0"
}
}
},
{
"requiredOS": {
"$elemMatch": {
"name": "windows",
"version": "2008"
}
}
}
]
})
So it just a matter of transforming the properties in the request to actually match the required query form.
Building this into a query object can be done in a number of ways, such as using the Query builder:
DBObject query = new Query(
new Criteria().andOperator(
Criteria.where("requiredOS").elemMatch(
Criteria.where("name").is("linux").and("version").is("6.0")
),
Criteria.where("requiredOS").elemMatch(
Criteria.where("name").is("windows").and("version").is("2008")
)
)
).getQueryObject();
Which you can then pass in to a mongoOperations method as a query object or any other method that accepts the query object.

Resources