I have a complex query that needs to be performed on given relationships (INNER JOINS) that are not defined in the Symfony schema. The query itself already takes quite some time, so I've opted to exclude it from the Doctrine schema and elected to use raw queries isntead. However, I would still like to to use the Doctrine pagination within the Symfony framework. Is this possible?
Yes it is.
After you create the query with Doctrine_RawSql you just have to add it to the pager. For example:
$query = new Doctrine_RawSql();
$query->addComponent('a', 'Class')->where('a.id = ?', 1);
$pager = new sfDoctrinePager('Class', 25);
$pager->setQuery($query);
$pager->init();
Related
Grails gives the possibility of creating simple string/value map properties section "Maps of Objects", first paragraph.
I was wondering, is there a way to later query the domain class (using Gorm dynamic finders, criterias or HQL) using the map property as part of the query (i.e adding a condition for the key X to have the value Y)?
After playing with it a bit and almost give up, I discovered the map syntax to (surprisingly) work in HQL. Assuming the class looks like:
class SomeClass {
Map pairKeyProperty
}
You can build queries that look like the following:
select * from SomeClass sc where sc.pairKeyProperty['someKey'] = 'someValue' and sc.pairKeyProperty['someOtherKey'] = 'someOtherValue'
Pretty neat! I still would prefer to use criterias as they are much cleaner to compose, but they seem to not support the same syntax (or I couldn't find it).
I created a sample app in GitHub:
https://github.com/deigote/grails-simple-map-of-string-value-pairs
It can be visisted at:
http://grails-map-of-string-pairs.herokuapp.com/
The form above uses a cross join. To enforce an inner join use
join sc.pairKeyProperty pk1 on index(pk1) = 'someKey'
where 'someValue' in elements(pk1)
I am using breeze to call a web api method which is:
Repository.ShipmentAppeals.Where(sa => sa.ShipmentID == shipmentID).Select(sa => sa.Appeal).Include("Case");
My breeze query looks like:
var query = EntityQuery.from('GetEditShipmentAppeals')
.withParameters({ shipmentID: shipmentID, caseID: caseID })
.orderByDesc("Case.ID")
GetEditShipmentAppeals is a web api method that contains the first query. In spite of using .Include("Case") in the query I am not able to use "Case.ID" in the order by clause of breeze query.
var query = EntityQuery.from('Appeals')
.expand("Case,Patient")
.orderByDesc("Case.ID").inlineCount();
Even if I use navigation property on a breeze query that does not involve a EF query in web api, it does not work. In above query Case is a navigation property in Appeal table.
If I understand your example correctly, then I think that this is an Entity Framework issue. My understanding is that Entity Framework does not support "Includes" on a projection. See http://connect.microsoft.com/VisualStudio/feedback/details/347543/entity-framework-eager-loading-not-working-in-some-projection-scenarios.
To confirm this, I would try executing your EF query in isolation and see if the "Include" is actually doing anything. My guess is that it isnt.
However, you can still accomplish what you want with a slightly different server side projection. ( I'm not sure what object 'Case' is a property of and the syntax may be a bit off but...) Something like:
Repository.ShipmentAppeals.Where(sa => sa.ShipmentID == shipmentID).Select(sa => new
{ Appeal: sa.Appeal, Case: sa.Appeal.Case, CaseId: sa.Appeal.Case.Id });
Note that Breeze will return a collection of 'anonymous' javascript objects from this query, but each of the 'entities' within each of these objects (i.e. Appeals and Cases) will be full Breeze entities and will be part of the EntityManager cache.
can I, and if I can, how, write LINQ statement like this:
public IQueryable<Advert> SearchSimilarAdverst(string query)
{
Levenshtein compute = new Levenshtein();
return _db.Adverts.Where(a => a.IsActive &&
(compute.FindSimilarity(a.Name, query) <= 2));
}
Thanks
EDIT
I've tired solution Jeffery suggested and it worked but when I've tried this line of code I got EntityCommandExecutionException, does anybody know why ?
adverts.Where(a => a.WhoAmILookingForTags.Any
(t => compute.FindSimilarity(t.Name,query) <= 2));
Tags and Adverts are connected with many to many relation, and WhoAmILookingForTags is list of tags
EF will not be able to translate compute.FindSimilarity(a.Name, query) to SQL, so you're going to have to take the performance hit and do the following.
public IEnumerable<Advert> SearchSimilarAdverst(string query)
{
Levenshtein compute = new Levenshtein();
var adverts = _db.Adverts.Where(a => a.IsActive).ToList();
return adverts.Where(a => compute.FindSimilarity(a.Name, query) <= 2));
}
Note the return type of the method also needed to be changed to reflect the return type
As commented below, the query should be forced to run before filtering using FindSimilarity because of delayed execution. query.ToList() is one of many options.
In short, no - because EF needs to be able to convert your Linq predicate into T-SQL (or whatever dialect of SQL your RDBMS uses). Only a subset of .NET BCL functions are supported (such as String.Contains and custom user code is right-out).
For complicated predicates I recommend writing your own SQL by hand - you'll also get considerably better performance, EF can be slow at generating SQL.
I hope I'm wrong on this, but I do not believe that you would be allowed to that in a Linq-to-Entities query. In those kinds of LINQ queries it has to translate everything in the Where function into a SQL statement to be run on the underlying database. Since your method is not something that is on the SQL side of things, it will cause an exception when you try this.
For a regular LINQ query (i.e. after everything has already been put into memory), there should be no problem with accomplishing this.
You could also try it and see if it does or does not work...
I want to retrieve the 10 nearest geolocalized objects using Gorm.
To do so, I would like to customize the order() parameter in order to use a get_distance(longitude, latitude, :longitude, :latitude) sql function.
I've been struggling with this all day, does anybody have a hint ?
Thanks !
EDIT
I finally managed to do what I wanted but with a very ugly solution :
I added a sqlProjection in which I put my get_distance() function and was able to order by it.
Adding a projection removes the retrieval of the object properties so I had to explicitly ask for it by adding property projections and I managed to do it with introspection.
Then I had to define the result transformer of the criteria for it to give me domain instances.
If register your function with the hibernate SQL dialect, then you can use it in HQL queries. For example, put this in your bootstrap code:
import org.hibernate.dialect.function.SQLFunctionTemplate
import org.hibernate.Hibernate
def dialect = applicationContext.sessionFactory.dialect
def getDistance = new SQLFunctionTemplate(Hibernate.INTEGER, "get_distance(?1,?2)")
dialect.registerFunction('get_distance', getDistance)
Then you can use it in HQL:
Location.executeQuery(
"""
select id, get_distance(latitude, longitude) as distance
from Location
order by distance
""",
[], [max: 10])
What we did is the following:
Create the query with whatever DB specific operators, but as a view
Create a new domain class object solely to map to the view, thereby allowing you to do GORM criteria queries and the like
I was wondering if it was possible to create a SPARQL UpdateRequest in Jena by using ARQ Op objects. I would be interested to create programmatically updates like this:
DELETE {?s :predicate <http://example.org#old> }
INSERT {?s :predicate <http://example.org#toAdd>}
WHERE {?s :predicate <http://example.org#old> }
by creating the patterns in the DELETE, INSERT, and WHERE clauses from the ARQ API.
So far the only ways I have found to create SPARQL Update requests require to parse a SPARQL string or to create a com.hp.hpl.jena.update.Update object (which uses QuadAcc objects for which I couldn't find examples of use.
My fear is that the management of SPARQL UPDATE requests and the one of SPARQL SELECT queries are separated and that ARQ cannot be used to 'assemble' queries on the fly.
Thanks in advance
This question also burned me. I wanted to compose an UpdateRequest from ElementGroup objects and ElementTriplesBlock objects. This are the two main classes used to construct a Query. For example:
ElementGroup queryPattern = ...
ElementTriplesBlock constructTriples = ...
Query query = new Query();
query.setQueryConstructType();
// set CONSTRUCT clause
query.setConstructTemplate(new Template(constructTriples.getPattern()));
// set WHERE clause
query.setQueryPattern(queryPattern);
I tried the Jena mailing-list and received this answer:
The Update API is designed to deal with streaming arbitrarily large
unbounded INSERT and DELETE data hence the use of QuadAcc rather than
an Element for the INSERT/DELETE portion of the update.
Eventually I implemented this using a ParametrizedSparqlString:
ElementGroup queryPattern = ...
ElementTriplesBlock deleteTriples = ...
ElementTriplesBlock insertTriples = ...
ParameterizedSparqlString qstring = new ParameterizedSparqlString();
// Set DELETE clause
qstring.append("DELETE {");
qstring.append(deleteTriples.toString());
qstring.append("}");
// Set INSERT clause
qstring.append("INSERT {");
qstring.append(insertTriples.toString());
qstring.append("}");
// Set WHERE clause
qstring.append("WHERE {");
qstring.append(queryPattern.toString());
qstring.append("}");
// Construct an update query
UpdateRequest request = qstring.asUpdate();
I haven't tried this myself, but it looks like creating Update objects and assembling them into an UpdateRequest is indeed the way to go.
After a short look, QuadAcc doesn't seem particularly difficult, just use addTriple() with triples that contain variables.
The UpdateModify subclass of Update looks particularly interesting, it corresponds to the DELETE … INSERT … WHERE pattern in your example. Unfortunately the WHERE clause is initialised with an Element (syntactic representation of a query part) rather than an Op (algebraic representation).