Removing a field and updating another field in a document - rethinkdb

Is it possible to remove a field from a document and update another field in the same document in one query?
Afaik, to remove field, you have to use a replace query, like so:
r.db("db").table("table").get("some-id").replace(r.row.without("field-to-remove"))
And to update:
r.db("db").table("table").get("some-id").update({ "field-to-update": "new-value" })
But chaining these two together doesn't work. I get a "RqlRuntimeError: Expected type SELECTION but found DATUM" error when running the following query (the order of the replace/update doesn't matter):
r.db("db").table("table").get("some-id").replace(r.row.without("field-to-remove")).update({ "field-to-update": "new-value" })

Try:
r.db('db').table('table').get('id').update({
"field-to-remove": r.literal(),
"field-to-update": "new-value"
})
You don't need to use replace here since you don't care about explicitly setting the other fields.

You can use replace with without and merge inside of your replace function:
r.table('30514947').get("492a41d2-d7dc-4440-8394-3633ae8ac337")
.replace(function (row) {
return row
.without("remove_field")
.merge({
"field-to-update": "hello"
})
})

Related

Filtering a list of values by a field value in GraphQL

So I'm doing some tests with GraphQL, and I'm failing in doing something that I believe is fairly simple.
When going to the GraphQL demo site (https://graphql.org/swapi-graphql) I'm presented with a default query which goes like this:
{
allFilms {
films {
title,
director,
releaseDate
}
}
}
This works as expected and returns a list of films.
Now - I would like to modify this query to return only the films where the director is George Lucas, and for the life of me - I can't figure out how to do that.
I've tried using the where and filter expressions, and also change the second line to films: (director: "George Lucas") but keep getting error messages.
What's the correct syntax for doing that?
Thanks!
If you check the docs of the provided GraphQL schema, you'll see that this is not possible. Following is the definition of the allFilms field:
allFilms(
after: String
first: Int
before: String
last: Int
): FilmsConnection
As per the doc, it has 4 input arguments, which are after, first, before, and last. There is no way to filter this out using the director's name.
GraphQL is not SQL. You cannot use expressions like WHERE or FILTER in GraphQL. The schema is already defined and the filters are pre-defined too. If the schema does not allow you to filter values using a certain field, you just can't do it.
You can to see the graphql schema here https://github.com/graphql/swapi-graphql/blob/master/schema.graphql
The allFilms query does not contain a filter for the field director. Also i can't find other query with this filter.
Most likely you need to write a filter on the result of the query.

Cypress: Is it possible to select an item out of a dynamic dropdown with only a partial word/s?

I have a dropdown list which is always increasing in the number of options available. I Have the 'RecieptName' from the option, however, it is followed by text that is constantly changing. eg: RecieptName: 'Changing sentence including words and numbers'.
What I am trying to do is something along the lines of:
cy.get('#RecieptName').select('RecieptName:');
However, it can't find an option with it as it is followed by changing the numbers. Is it possible to find the option based on a partial option?
You would need to scan the options first, find it's index and select by number
Using .contains() command
cy.get('option')
.contains('ReceiptName:')
.invoke('index') // index among siblings
.then(index => {
cy.get('dropdown').select(index);
})
Using a regex
cy.get('option')
.contains(/^ReceiptName:/)
.invoke('index') // index among siblings
.then(index => {
cy.get('dropdown').select(index);
})
Using selected prop
cy.get('#RecieptName option')
.contains(/^ReceiptName:/)
.invoke('prop', 'selected', true)
The option containing the the text "RecieptName:" can be selected by adding :contains()
cy.get('#RecieptName option:contains(RecieptName:)')
.then($option => {
cy.get('#RecieptName').select($option.text())
})
cy.get('#RecieptName option:contains(RecieptName:)')
.then($option => {
cy.get('#RecieptName').select($option.index())
})
filter will get the DOM element that match a specific selector. Once we get the element, then we get the exact text of RecieptName option by using the invoke(text) and then we pass the same text to the select command, something like this:
cy.get('#RecieptName option')
.filter(':contains("RecieptName:")')
.invoke('text')
.then((recieptNameText) => {
cy.get('dropdown').select(recieptNameText)
})
You can also use the value attribute to directly select the dropdown as I can see the value attributes are unique, I guess that would be the cleanest way to do this:
cy.get('select#RecieptName').select('scoredesc')
cy.get('select#RecieptName').select('modifieddesc')
cy.get('select#RecieptName').select('createdasc')

How to update item conditionally with branch in RethinkDB

I am trying to do simple upsert to the array field based on branch condition. However branch does not accept a reql expression as argument and I get error Expected type SELECTION but found DATUM.
This is probably some obvious thing I've missed, however I can't find any working example anywhere.
Sample source:
var userId = 'userId';
var itemId = 'itemId';
r.db('db').table('items').get(itemId).do(function(item) {
return item('elements').default([]).contains(function (element) {
return element('userId').eq(userId);
}).branch(
r.expr("Element already exist"),
//Error: Expected type SELECTION but found DATUM
item.update({
elements: item('elements').default([]).append({
userId: 'userId'
})
})
)
})
The problem here is that item is a datum, not a selection. This happens because you used r.do. The variable doesn't retain information about where the object originally came from.
A solution that might seem to work would be to write a new r.db('db').table('items').get(itemId) expression. The problem with that option is the behavior isn't atomic -- two different queries might append the same element to the 'elements' array. Instead you should write your query in the form r.db('db').table('items').get(itemId).update(function(item) { return <something>;) so that the update gets applied atomically.

rethinkdb - hasFields to find all documents with multiple multiple missing conditions

I found an answer for finding all documents in a table with missing fields in this SO thread RethinkDB - Find documents with missing field, however I want to filter according to a missing field AND a certain value in a different field.
I want to return all documents that are missing field email and whose isCurrent: value is 1. So, I want to return all current clients who are missing the email field, so that I can add the field.
The documentation on rethink's site does not cover this case.
Here's my best attempt:
r.db('client').table('basic_info').filter(function (row) {
return row.hasFields({email: true }).not(),
/*no idea how to add another criteria here (such as .filter({isCurrent:1})*/
}).filter
Actually, you can do it in one filter. And, also, it will be faster than your current solution:
r.db('client').table('basic_info').filter(function (row) {
return row.hasFields({email: true }).not()
.and(row.hasFields({isCurrent: true }))
.and(row("isCurrent").eq(1));
})
or:
r.db('client').table('basic_info').filter(function (row) {
return row.hasFields({email: true }).not()
.and(row("isCurrent").default(0).eq(1));
})
I just realized I can chain multiple .filter commands.
Here's what worked for me:
r.db('client').table('basic_info').filter(function (row) {
return row.hasFields({email: true }).not()
}).filter({isCurrent: 1}).;
My next quest: put all of these into an array and then feed the email addresses in batch

How to use RethinkDB indices in the following scenario?

I'd like to use an index to select all documents that don't have a particular nested field set.
In my situation with the JS-api this works out to this:
r.table('sometable').filter(r.row('_state').hasFields("modifiedMakeRefs").not())
How would I use an index on the above? I.e.: filter doesn't support defining indices afaik?
You would write:
r.table('sometable').indexCreate('idx_name', function(row) {
return row('_state').hasFields("modifiedMakeRefs");
})
And then:
r.table('sometable').getAll(false, {index: 'idx_name'})

Resources