Hybris Impex import based on PKs obtained from FlexQuery - sap-commerce-cloud

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
}

Related

Android Studio Room query to get a random row of db and saving the rows 2nd column in variable

like the title mentions I want a Query that gets a random row of the existing database. After that I want to save the data which is in a specific column of that row in a variable for further purposes.
The query I have at the moment is as follows:
#Query("SELECT * FROM data_table ORDER BY RANDOM() LIMIT 1")
fun getRandomRow()
For now I am not sure if this query even works, but how would I go about writing my function to pass a specific column of that randomly selected row to a variable?
Ty for your advice, tips and/or solutions!
Your query is almost correct; however, you should specify a return type in the function signature. For example, if the records in the data_table table are mapped using a data class called DataEntry, then the query could read as shown below (note I've also added the suspend modifier so the query must be run using a coroutine):
#Query("SELECT * FROM data_table ORDER BY RANDOM() LIMIT 1")
suspend fun getRandomRow(): DataEntry?
If your application interacts with the database via a repository and view model (as described here: https://developer.android.com/topic/libraries/architecture/livedata) then the relevant methods would be along the lines of:
DataRepository
suspend fun findRandomEntry(): DataEntry? = dataEntryDao.getRandomRow()
DataViewModel
fun getRandomRecord() = viewModelScope.launch(Dispatchers.IO) {
val entry: DataEntry? = dataRepository.findRandomEntry()
entry?.let {
// You could assign a field of the DataEntry record to a variable here
// e.g. val name = entry.name
}
}
The above code uses the view model's coroutine scope to query the database via the repository and retrieve a random DataEntry record. Providing the returning DataEntry record is not null (i.e. your database contains data) then you could assign the fields of the DataEntry object to variables in the let block of the getRandomRecord() method.
As a final point, if it's only one field that you need, you could specify this in the database query. For example, imagine the DataEntry data class has a String field called name. You could retrieve this bit of information only and ignore the other fields by restructuring your query as follows:
#Query("SELECT name FROM data_table ORDER BY RANDOM() LIMIT 1")
suspend fun getRandomRow(): String?
If you go for the above option, remember to refactor your repository and view model to expect a String instead of a DataEntry object.

Casting Strint to integer in liferay dynamic query

I have been using dynamic query for a project.
Here is an scenario for which I am facing problem.
For a table xyz the column version is stored as varchar (I know it's a poor design, but it's too late to change now) and has values as 9,12.
For the query :
select max(version)
from xyz
where something = 'abc';
I am getting the output as 9 instead of 12.
The dynamic query for the same is:
ClassLoader classLoader = PortletBeanLocatorUtil.getBeanLocator(ClpSerializer.getServletContextName()).getClassLoader();
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(xyz.class, classLoader);
dynamicQuery.setProjection(ProjectionFactoryUtil.max("version"));
dynamicQuery.add(PropertyFactoryUtil.forName("something").eq("abc"));
List<Object> list = xyzLocalServiceUtil.dynamicQuery(dynamicQuery);
The query which is giving the correct value is :
select max(cast(version as signed))
from xyz
where something = 'abc';
Now, I want it to be in the dynamic query, how can I do that?
I am using liferay-6.2-ce
Try using ProjectionFactoryUtil.sqlProjection method.
That method allows using functions that are executed by SQL engine.
For example, I am using following code in order to get the max length of a string column called 'content':
Projection maxSizeProjection = ProjectionFactoryUtil.sqlProjection(
"max(length(content)) as maxSize", new String[] {"maxSize"},
new Type[] {Type.BIG_DECIMAL});
The same thing can be done with dynamic query criterions using RestrictionsFactoryUtil.sqlRestriction in case you want to use a SQL function in a condition.
In your case try following code:
import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
import com.liferay.portal.kernel.dao.orm.Type;
...
Projection maxSizeProjection = ProjectionFactoryUtil.sqlProjection(
"max(cast(version as signed)) as maxVersion",
new String[] {"maxVersion"}, new Type[] {Type.BIG_DECIMAL});
dynamicQuery.setProjection(maxSizeProjection);

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 :)

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

Removing a column from result set in Groovy Sql rows

I have a query where I need to retrieve a column which I need only temporarily because I need to pass it in the parameter for a where clause, how can I remove this column and its value from my result set after it served that purpose. Hopefully the code will show what I mean...
def empQuery = "select id, name, address from Employee"
def retObj = [:]
def sql = new Sql(datasource)
retObj = sql.rows(empQuery.toString())
retObj.each {
def addressQuery = "select street from Address where employe_id = ${it['id']}
// at this point I want to remove 'id:n' from the result set hash map aka 'it'
}
Because later on I am displaying that result set on a page for the user, and the ID field is not relevant.
So can you please show the Groovy code to remove a column and its value from the rows data structure returned from sql.rows?
from http://docs.groovy-lang.org/latest/html/api/groovy/sql/GroovyRowResult.html
It looks like you can do something line:
retObj.each { it.remove('id')}
However I haven't tried it....

Resources