I was looking at my profiler and it seem that the Linq extension method Single selects 2 rows. So why does the Single LINQ extension method create a query Select TOP(2)? Shouldn't it be select top(1) instead?
First only requests a single result. Single requests two results because it only returns a result if there is exactly one member of the result set. If there are zero or two (or more than two) it throws an exception, so it has to request at least two results.
Related
Hello experts of the world. Need some help concerning executing a query with SpringData.
The expectation is to execute the Query below in the Spring Data annotation by combining with the repository method name (Automated Query Construction) to get a unique result. Apparently it fails from time to time by saying the result is not Unique.
The question here is if the method name is still considered in Query Construction while also executing the query in the annotation.
#Query("SELECT r from Revision r WHERE r.revisionBid = ?1 AND r.revisionStatusId = ?2 ORDER BY r.lastModifiedDate DESC")
Optional<Revision> findFirst(Integer revisionBid, Integer revisionStatusId);
Thanks in advance!
The query creation for limiting to 1 result is defined here with FIRST & TOP included in the method name.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
I don't think "findFirst" will work when you're using an #Query, as the query will be constructed from HQL expression in the #Query rather than the fluent API passing over the method name. Because of this, when the query returns multiple results, it will throw the exception as the Optional is told to wrap a single returned object, not a collection. Add a LIMIT clause to the HQL query and you should be good.
I have a class that contains a LINKMAP field called links. This class is used recursively to create arbitrary hierarchical groupings (something like the time-series example, but not with the fixed year/month/day structure).
A query like this:
select expand(links['2017'].links['07'].links['15'].links['10'].links) from data where key='AAA'
Returns the actual records contained in the last layer of "links". This works exactly as expected.
But a query like this (note the 10,11 in the second to last layer of "links"):
select expand(links['2017'].links['07'].links['15'].links['10','11'].links) from data where key='AAA'
Returns two rows of the last layer of "links" instead:
{"1000":"#23:0","1001":"#24:0","1002":"#23:1"}
{"1003":"#24:1","1004":"#23:2"}
Using unionAll or intersect (with or without UNWIND) results in this single record:
[{"1000":"#23:0","1001":"#24:0","1002":"#23:1"},{"1003":"#24:1","1004":"#23:2"}]
But nothing I've tried (including various attempts at "compound" SELECTs) will get the expand to work as it does with the original example (i.e. return the actual records represented in the last LINKMAP).
Is there a SQL syntax that will achieve this?
Note: Even this (slightly modified) example from the ODB docs does not result in a list of linked records:
select expand(records) from
(select unionAll(years['2017'].links['07'].links['15'].links['10'].links, years['2017'].links['07'].links['15'].links['11'].links) as records from data where key='AAA')
Ref: https://orientdb.com/docs/2.2/Time-series-use-case.html
I'm not sure of what you want to achieve, but I think it's worth trying with values():
select expand(links['2017'].links['07'].links['15'].links['10','11'].links.values()) from data where key='AAA'
This seems like a rather simple query but I've been banging my head for hours on this. I've got a node structure similar to below:
food-group
jcr:content
nuts -> type=almonds
meat -> beef=true
fruit -> type=apples,oranges,bananas
There are three types of properties I need to gather from my child nodes: one that is a string, boolean and string array. I would think that the following sql2 query would work and get the properties of them but for whatever reason I'm getting an error:
QUERY
SELECT
parent.*
FROM
[cq:PageContent] AS parent
INNER JOIN
[nt:base] as child ON ISCHILDNODE(parent)
WHERE
ISDESCENDANTNODE(parent, [/content/grocerystore/food/])"
ERROR:
Need to specify the selector name because the query contains more than one selector.
Any help is appreciated as I've been at this for the past few days.
There are two places the ISCHILDNODE function can be used in a JCR-SQL2 query: in the WHERE clause and in the join criteria. Unfortunately, they take different parameters.
Your query is attempting to use the ISCHILDNODE in the join criteria, which requires two parameters: the selector name for the child nodes, and the selector name for the parent nodes.
Here's the query I think you want:
SELECT parent.*
FROM [cq:PageContent] AS parent
INNER JOIN [nt:base] as child ON ISCHILDNODE(child,parent)
WHERE ISDESCENDANTNODE(parent, [/content/grocerystore/food/])
The only change is the parameters to the ISCHILDNODE function.
Unfortunately, the error message doesn't really make this clear. To understand why, it helps to know about the other form of ISCHILDNODE - the one used in the WHERE clause. That form also takes two parameters: the name of the selector that will represent the child nodes, and the literal path of the parent (under which the resulting nodes are children). Here's a contrived query that uses this form:
SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE(node,[/content/grocerystore])
The query result would contain all nodes that are children of the /content/grocerystore node.
Now, if the query defines just one selector (e.g., a non-join), then there is only one selector name that can be passed to the ISCHILDNODE function. Strictly speaking, the selector is implicitly known, so JCR-SQL2 allows you to pass in just the path. Here's a query that is semantically identical to the previous contrived example:
SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE([/content/grocerystore])
This is the only form of the ISCHILDNODE that takes a single parameter, and I think this is the form that I think CQ5 is expecting: the error says that the query defines more than one selector, so the selector must be supplied as the first parameter.
Of course, this is very misleading because you're actually using the form of the function that appears in the join criteria. A better error message would say that function requires the child selector name and the parent selector name.
This exception will be thrown if you invoke getNodes() method on a QueryResult that have more than one selector (in your case it's parent and child). This method will also be used if you call findResources() on the ResourceResolver.
Use the QueryResult#getRows() method instead:
Session session = resourceResolver.adaptTo(Session.class);
QueryManager queryManager = session.getWorkspace().getQueryManager();
Query query = queryManager.createQuery("...", Query.JCR_SQL2);
QueryResult result = query.execute();
// consider using result.getColumnNames() here
RowIterator rows = result.getRows();
while (rows.hasNext()) {
Row row = rows.nextRow();
// use row.getValue() or row.getValues()
}
A few remarks:
You need to fix the SQL query adding child as the first parameter to the ISCHILDNODE(parent).
Pass properties list explicite in the SELECT clause rather than using parent.*, so you don't have to invoke result.getColumnNames().
The query is quite complex and the way to invoke it is even more complex. Why don't you use Sling methods to iterate over the food space in your repository? It seems to be a perfect use-case for iterating over the tree.
You may be also interested in the SlingQuery project.
I want to do something like this in OrmLite
SELECT *, COUNT(title) as titleCount from table1 group by title;
Is there any way to do this via QueryBuilder without the need for queryRaw?
The documentation states that the use of COUNT() and the like necessitates the use of selectRaw(). I hoped for a way around this - not having to write my SQL as strings is the main reason I chose to use ORMLite.
http://ormlite.com/docs/query-builder
selectRaw(String... columns):
Add raw columns or aggregate functions
(COUNT, MAX, ...) to the query. This will turn the query into
something only suitable for using as a raw query. This can be called
multiple times to add more columns to select. See section Issuing Raw
Queries.
Further information on the use of selectRaw() as I was attempting much the same thing:
Documentation states that if you use selectRaw() it will "turn the query into" one that is supposed to be called by queryRaw().
What it does not explain is that normally while multiple calls to selectColumns() or selectRaw() are valid (if you exclusively use one or the other),
use of selectRaw() after selectColumns() has a 'hidden' side-effect of wiping out any selectColumns() you called previously.
I believe that the ORMLite documentation for selectRaw() would be improved by a note that its use is not intended to be mixed with selectColumns().
QueryBuilder<EmailMessage, String> qb = emailDao.queryBuilder();
qb.selectColumns("emailAddress"); // This column is not selected due to later use of selectRaw()!
qb.selectRaw("COUNT (emailAddress)");
ORMLite examples are not as plentiful as I'd like, so here is a complete example of something that works:
QueryBuilder<EmailMessage, String> qb = emailDao.queryBuilder();
qb.selectRaw("emailAddress"); // This can also be done with a single call to selectRaw()
qb.selectRaw("COUNT (emailAddress)");
qb.groupBy("emailAddress");
GenericRawResults<String[]> rawResults = qb.queryRaw(); // Returns results with two columns
Is there any way to do this via QueryBuilder without the need for queryRaw(...)?
The short answer is no because ORMLite wouldn't know what to do with the extra count value. If you had a Table1 entity with a DAO definition, what field would the COUNT(title) go into? Raw queries give you the power to select various fields but then you need to process the results.
With the code right now (v5.1), you can define a custom RawRowMapper and then use the dao.getRawRowMapper() method to process the results for Table1 and tack on the titleCount field by hand.
I've got an idea how to accomplish this in a better way in ORMLite. I'll look into it.
I am querying the Nhibernate criteria query with more then 2100 values for In clause.
I do something like Session.CreateCriteria(typeof()).Add(Expression.In("fieldName",arrayValue))
Where arrayValue contains more then 2100 values. I face error
Exception occurred:
UnknownError
NHibernate.ADOException: could not execute query ..then the query with more then 3000 values in array.
with some google help we found out that IN clause in Sql supports only till 2100 values.
Does anyone has faced similar issue earlier? We do not want to change the query as it is written in some generic way and not customized one.
This is a limitation of SQL Server. I wouldn't suggest doing this, but if you insist, you could work around it by creating a table-value sql function (see http://www.dzone.com/snippets/function-getting-comma) that splits up a string by commas (or whatever delimiter you want) and returns the values as a table, and then pass in all your ID's as (say) a comma separated list in 1 parameter and use a SQLCriterion in your criteria query.
eg:
criteria.Add(
new SQLCriterion("{alias}.ID IN (SELECT element FROM dbo.GetCSVValues(?))",
new[]{csvListOfIds},
new[]{NHibernateUtil.String}))
You could split the array into multiple batches, query multiple times, and then combine the result.