How to return only first result using #Query notation? - jpql

I am making a query using a method defined through the #Query annotation in the Spring Framework.
#Transactional(readOnly=true)
#Query("SELECT x FROM X x ORDER BY x.id ASC")
List<X> findLowest();
I am currently returning a list of items, but I really only want to return the first one.
How can I do this?

First, you should add a Pageable object to your method like this:
#Transactional(readOnly=true)
#Query("SELECT x FROM X x ORDER BY x.id ASC")
List<X> findLowest(Pageable pageable);
and to use in this way:
Pageable firstResult = new PageRequest(0, 1);
List<X> result = repository.findLowest(firstResult);
In this way, you can reuse this method another time.

Related

Hybris Impex import based on PKs obtained from FlexQuery

What I want to achieve:
I want to set the value of two attributes, a1 and a2, to null for any product where a third attribute, a3, has a specific enum value.
What I have so far:
I have a flexquery which fetches a list of PKs for products which fulfill the requirement for a3. I now need to set the attributes of the products with those specific keys. The query is as follows:
SELECT {p.pk} FROM {Product AS p JOIN ProductOrigin AS o ON {o.pk} = {p.origin}} WHERE {o.code} = 'MARKETPLACE'
What I need help with:
I do not know how to combine the results of the flexquery with a typical impex operation. What I ideally want is to be able to simply pass the list of PKs to an INSERT_UPDATE as in:
INSERT_UPDATE Product; pk ; a1 ; a2 ;
queryResult; null; null;
I do not know if this is possible however. Even better would be if there is an even easier way to do this that I have not thought of.
Hi Erik you can achieve this even without using the Impex header and use groovy, steps are below.
Create groovy
#%impex.enableCodeExecution(true);
"#%groovy%
def queryCreditCardsToRemove = ''' SELECT {p.pk} FROM {Product AS p JOIN ProductOrigin AS o ON {o.pk} = {p.origin}} WHERE {o.code} = 'MARKETPLACE''''
def products = (Collection<ProductModel>)flexibleSearchService.search(queryCreditCardsToRemove).result
products.stream()
.each{
modelService
}
modelService.removeAll(cardsToRemove)
";
Save the file as impex
3.# Disable legacy scripting (makes groovy work at impex)
impex.legacy.scripting=false---> either you can change dynamically via hac-->configuration or add in local.properties
here is one beanshell script, execute it from hac -> console -> scripting languages!
In the below script, you need to put query that will give you result which is expected to you and on that result script will do further operations of saving null values to attributes!
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import de.hybris.platform.servicelayer.search.SearchResult;
import de.hybris.platform.core.model.product.ProductModel
import de.hybris.platform.variants.model.VariantProductModel;
final Map<String, Object> params = new HashMap<String, Object>();
String query = "-------------- query to check condition of third (a3) attribute
with specific enum value ----------------------"
params = -----------if any need to be passed in query ------------------;
FlexibleSearchService fss = spring.getBean("flexibleSearchService")
final SearchResult<ProductModel> searchResult = fss.search(query, params);
for (final ProductModel product : searchResult.getResult()) {
// set attributes a1 and a2 to null
// save product model using modelService
}

Find distinct values from column of datatable in c# and store distinct values in variables

i want to find distinct values from a column of datatable in c# and also want to store all these distinct values in variables
DataTable dtable = new DataTable();
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * from clubbb ", con);
da.Fill(dtable, "clubbb");
int toto = bdtable.AsEnumerable().Distinct().Count();
You need to implement the interface IEqualityComparer<DataRow> methods to provide the way the Distinct method will use to know whether 2 rows are duplicate or not. This can be achieved with a class like this:
public class CustomComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
// your custom equality logic here
}
public int GetHashCode(DataRow obj)
{
// return hash code depending on your distinct criteria
}
}
Then change the call you made:
int toto = bdtable.AsEnumerable().Distinct(new CustomComparer()).Count();
I had similar problem, and in my case I needed to know distinct values of specific column, so I passed the name of this column to the custom comparer I implemented, so that GetHashCode will return identical hash codes for duplicate values.
You can read more here: https://msdn.microsoft.com/en-us/library/ms132151(v=vs.110).aspx
Hope this helps :)

Hazelcast - query collections of Map values

Assume I have the following as the value in an IMap:
public class Employee{
public int empId;
public List<String> categories;
public List<String> getCategories(){
return this.categories;
}
}
I would like to find all employees that belong to category "Sales". Also, I would like to create an index on getCategories() so that the query returns fast. There seems to be no Predicate available to do this. How do I go about achieving this? It seems like I will have to write a Predicate to do this. Is there example code I can look at that would show me how to build a predicate that uses an index ?
The only way I currently see this happening is to denormalize the data model and use something like a IMap and the following as value:
class EmployeeCategory{int employeeId, String category}
And put an index on category.
It is somewhere on the backlog to provide more advances indices that should be able to do this out of the box.
I tried by iterating the List to a separate Imap and then querying it in the client.
IMap<String,ArrayList< categories >> cache=hazelcastInstance.getMap("cache");
IMap<String, categories> cachemodified = hazelcastInstance.getMap("cachemodified") ;
int[] idx = { 0 };
xref.get("urkey").forEach(cachefelement ->{
cachemodified.put(String.valueOf(idx[0]++),cachefelement);
});
Predicate p = Predicates.equal("categoryId", "SearchValue");
Collection<categories> result = cachemodified.values(p);

Sorting DAM asset and Cq page based on last modified

I am trying to perform a freetext search on all the Cq:Page and dam:Asset with the ordering being the last modified.
I have created the Query for search which is as below:
1_group.p.or=true
1_group.1_type=cq:Page
1_group.2_type=dam:Asset
2_group.p.or=true
2_group.1_path=/content
2_group.2_path=/content/dam
fulltext=text
p.limit=-1
Now I need to sort the results based on last modified. But since cq:Page has property jcr:content/cq:lastModified and dam:Asset has property jcr:content/jcr:lastModified, I am unable to figure out which property should i use in the orderby field of predicate. Is there any way to form a predicate which uses different property values for pages and assets during sorting. Please let me know if we can achieve this in a single query.
Regards,
Shailesh
This can be done by creating a custom AbstractPredicateEvaluator and overriding the getOrderByComparator with your own comparator. Then you would register your custom predicate evaluator for your Query by calling registerPredicateEvaluator.
In the example below, you can use whatever you'd like for the customSort.sortby property. This can be useful if your comparator handles multiple types of sorting. You can get this information from the predicate via predicate.get("sortby").
QueryBuilder builder = resourceResolver.adaptTo(QueryBuilder.class);
Map<String, String> params = new HashMap<String, String>();
params.put("1_group", "true");
params.put("1_group.1_type", "cq:Page");
params.put("1_group.2_type", "dam:Asset");
params.put("2_group.p.or", "true");
params.put("2_group.1_path", "/content");
params.put("2_group.2_path", "/content/dam");
params.put("fulltext", text);
params.put("p.limit", "-1");
params.put("customSort.sortby", "last-modified");
PredicateGroup pg = PredicateGroup.create(params);
Query query = builder.createQuery(pg, resourceResolver.adaptTo(Session.class));
query.registerPredicateEvaluator("customSort", new CustomSortPredicateEvaluator());
SearchResult result = query.getResult();
there is no way since they are differenet type (cq:lastModified & jcr:lastModified), Even you use SQL2 like this (SELECT p.* FROM [nt:base] AS p WHERE ISDESCENDANTNODE(p, '/content') AND ( p.[jcr:primaryType]='dam:Asset' OR p.[jcr:primaryType]='cq:Page')) there no way to use ORDER BY.
Have to use Java code for sorting.
Keep your Query, get QueryResult to List and do Comparator Sort

What is wrong in this LINQ Query, getting compile error

I have a list AllIDs:
List<IAddress> AllIDs = new List<IAddress>();
I want to do substring operation on a member field AddressId based on a character "_".
I am using below LINQ query but getting compilation error:
AllIDs= AllIDs.Where(s => s.AddressId.Length >= s.AddressId.IndexOf("_"))
.Select(s => s.AddressId.Substring(s.AddressId.IndexOf("_")))
.ToList();
Error:
Cannot implicitly convert type 'System.Collections.Generic.List<string>' to 'System.Collections.Generic.List<MyCompany.Common.Users.IAddress>'
AllIDs is a list of IAddress but you are selecting a string. The compiler is complaining it cannot convert a List<string> to a List<IAddress>. Did you mean the following instead?
var substrings = AllIDs.Where(...).Select(...).ToList();
If you want to put them back into Address objects (assuming you have an Address class in addition to your IAddress interface), you can do something like this (assuming the constructor for Address is in place):
AllIDs = AllIDs.Where(...).Select(new Address(s.AddressID.Substring(s.AddressID.IndexOf("_")))).ToList();
You should also look at using query syntax for LINQ instead of method syntax, it can clean up and improve the readability of a lot of queries like this. Your original (unmodified) query is roughly equivalent to this:
var substrings = from a in AllIDs
let id = a.AddressId
let idx = id.IndexOf("_")
where id.Length >= idx
select id.Substring(idx);
Though this is really just a style thing, and this compiles to the same thing as the original. One slight difference is that you only have to call String.IndexOf() one per entry, instead of twice per entry. let is your friend.
Maybe this?
var boundable =
from s id in AllIDs
where s.AddressId.Length >= s.AddressId.IndexOf("_")
select new { AddressId = s.AddressId.Substring(s.AddressId.IndexOf("_")) };
boundable = boundable.ToList();

Resources