I notice that r.table('xxx') not always return a cursor but also sometimes just return docs directly
Is the cursor client side implementation only or there are some special things server did to perform queries associate with a cursor?
If it has somethings related to server, what is it and when will I receive a cursor
For example I specify result offset and size with skip and limit in the query. Will server return a cursor or just result docs?
A driver returns a cursor when the query returns a stream.
Basically when the server produces a stream (a sequence that is lazily computed), the driver will return a cursor. As you fetch rows from the cursor, the server will compute more elements in the sequence.
For example, when you run r.table('xxx'), you will get back a cursor. The server will load the documents from disk as you request them with the driver.
In the JavaScript driver, when a query return an array, the driver will sneak an object that mimics the cursor interface between the arrray itself and Array.prototype.
So if query.run(...) returns a sequence, you can just do
query.run(connection).then(function(result) {
return result.toArray()
}).then(function(result) {
// do something with result
}).error(function(err) {
// handle err
})
Basically if you don't want to think if you are getting back a cursor or an array, you can just consider that it's a cursor.
You can read more about stream/cursor here:
http://www.rethinkdb.com/docs/data-types/
Related
I have the following function in my base repository
public IEnumerable<T> GetAll(ClaimsPrincipal user)
{
return client.CreateDocumentQuery<T>(collectionLink)
.Where(doc => doc.Type == DocType)
.AsEnumerable()
.Where(doc =>
doc.Owner == user.Id()
|| user.InGroup(doc.Owner)
|| doc.Public);
}
I have two extension methods on the ClaimsPrincipal class. Id() just returns .FindFirst("user_id").Value and .InGroup(<id>) checks if the user has a group-membership to the group that owns the document.
However, am I correct in assuming that once I call .AsEnumerable() the query goes to the database with only the first where-clause, returns everything it matches, and then does the second where-clause on the client side?
However, am I correct in assuming that once I call .AsEnumerable() the query goes to the database
Not quite.
When this method returns, it won't have hit the database at all. AsEnumerable() doesn't force the query to execute - it's basically just a cast to IEnumerable<T>.
You're right in saying the first Where is performed at the database and the second Where is performed client-side, but "returns everything it matches" suggests that's done in bulk - which it might be, but it may be streamed as well. The client-side Where will certainly stream, but whether the IQueryable<T> implementation fetches everything eagerly is an implementation detail.
If you're really only interested in which filters are in the database and which are local though, you're correct.
How does graphql generates hasNextPage if only "first" parameter passed?
I am using
return relay.connectionFromPromisedArray(
global.app.get('model__user').getUsers(args),
args
);
and query:
query RootQueryType { viewer { user(id: 1){ id,email,friends(first: 5) {edges {cursor, node { id, email } }, pageInfo { hasNextPage } } } } }
So how can i pass to graphql / relay friends count so hasNextPage will be generated correct?
Relay pagination is not page based, but rather cursor based. So you paginate by saying "I want X items after item Y". Item Y is not pointed to as a page number or an offset, but rather as a pointer to that exact object, a so-called cursor. This model of pagination is nice for, for example, infinite scrolling. "Pages" are also stable after adding or removing items, as they don't depend on number of items.
hasNextPage in Relay GraphQL spec just indicates whether there are more items after the last element that has been retrieved. So in your case, it means there are more than 5 elements in total and you'll get more elements if you do
friends(first: 5, after: "CURSOR_TO_THE_LAST_ELEMENT")
You can retrieve cursor from the edges list, it's one of the elements alongside node there.
You can find detailed information on the relay pagination algorithm here: https://facebook.github.io/relay/graphql/connections.htm#sec-Pagination-algorithm.
To answer your specific question about hasNextPage, this is the algorithm:
function hasNextPage(allEdges, before, after, first, last) {
// If first was not set, return false.
if (first === null) { return false; }
// Apply the before & after cursor arguments to the set of edges.
// i.e. edges is the set of edges between the before and after cursors
const edges = ApplyCursorsToEdges(allEdges, before, after)
// If more edges exist between the before & after cursors than
// you are asking for then there is a next page.
if (edges.length > first) { return true; }
return false
}
A quick note on cursor vs page based pagination. It is generally a bad idea to paginate using fixed page sizes. A classic example of this is using the OFFSET keyword in SQL to grab the next page. There are many issues with this approach. For example, what would happen if a new object was inserted while you were in the middle of paginating the set? If the new object was inserted before the page you are currently grabbing and you use a fixed offset you are going to grab an object that you have already grabbed which leads to duplicate data in your presentation layer. Using cursors for pagination fixes this problem by allowing you to keep track of the objects themselves instead of counts of the objects.
Once last thing with relay pagination specifically. I recommend only using (first & after) OR (last & before) at any given time. Using both in the same query can lead to logical, yet unexpected results.
Best of luck!
I am currently using this:
params["RPBla"].join(",")
as default parameter of a (stored procedure) dataset. This works fine and sends one or more selected values from the report parameter RPBla to a stored procedure, e.g.:
1,2,3
Unfortunately, this does not work if the user does not select any value. Any ideas what to do. Actuate BIRT should send NULL instead of for example 1,2,3.
What about testing the content in this default value expression, something like:
if (params["RPBla"].value==null){
null;
}else{
var list=params["RPBla"].join(",");
list.length>0 ? list : null;
}
Of course you could return anything you need instead of "null" here, for example returning a specific value warning the stored procedure that the filter should be disabled.
I have a strange problem ,
My Query looks like below.
String tokenQuery = "select id from table
where current_timestamp between
creation_time and (creation_time + interval '10' minute)
and token = '"+Token+"'";
But when I run, jdbcTemplate.queryForLong(tokenQuery) , no matter what , it always throws EmptyDataAccessException.
I am executing this in Oracle
Can we not append dynamic values to string and then pass it as a query and execute ?
What could be the issue ?
I assume that what you get is in fact an EmptyResultDataAccessException. The javadoc of this exception says:
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
That simply means that the query is executed fine, and is supposed to return one row, but doesn't return any. So no row satisfies the criteria of your query.
If that is expected, then catch the exception, or use a method that returns a list rather then returning a single value. That way, you can test if the returned list is empty.
That said, you should use a parameterized query instead of concatenating the token like you're doing. This would prevent SQL injection attacks. It would also work even if the token contains a quote, for example.
I'm starting to learn how to use SQLAlchemy and I'm running into some efficiency problems.
I created an object mapping an existing big table on our Oracle database:
engine = create_engine(connectionString, echo=False)
class POI(object):
def __repr__(self):
return "{poi_id} - {title}, {city} - {uf}".format(**self.__dict__)
def loadSession():
metadata = MetaData(engine)
_poi = Table('tbl_ourpois', metadata, autoload = True)
mapper(POI, _poi)
Session = sessionmaker(bind = engine)
session = Session()
return session
This table have millions of registries. When I do a simple query and try to iterate over it:
session = loadSession()
for poi in session.query(POI):
print poi
I noticed two things: (1) it takes some minutes for it to start printing objects on the screen, (2) memory usage starts to grow like crazy. So, my conclusion was that this code was fetching all the result set in a list and then iterating over it. Is this correct?
With cx_Oracle, when I do a query like:
conn = cx_Oracle.connect(connectionString)
cursor = conn.cursor()
cursor.execute("select * from tbl_ourpois")
for poi in cursor:
print poi
the resulting cursor behaves as an iterator that gets results into a buffer and returns them as they are needed intead of loading the whole thing in a list. This loop starts printing results almost instantly and memory usage is pretty low and constant.
Can I get this kind of behavior wiht SQLAlchemy? Is there a way to get a constant memory iterator out of session.query(POI) instead of a list?