How to query the "Props" table from Flexible Search? - sap-commerce-cloud

Inside my code I have the primary keys of some page components in Hybris and I have to find all their attributes (properties like title, content etc.)
I can query the "Props" table using an SQL query, but I'm not sure how to find the equivalent in Flexible Search, since querying the database directly is not recommended.
Is there any other simpler way to retrieve all the properties of a component having just the primary key?

What you can do is retrieve the required component using it's primary key. Example:
select {pk} from {SimpleCMSComponent} where {pk} ='8796093056060'
Usually flexible searches are used in DAO classes(Platform example: DefaultProductDao).
When this flexible search is run by the flexible search service you get a ComponentModel. Please see below a groovy script I just created in order to exemplify how to print the ID of a Component retrieved based on its PK(In the same way by using getters you can get the title, content, etc.. ):
import de.hybris.platform.cms2.model.contents.components.SimpleCMSComponentModel;
def flexibleSearchService = spring.getBean("flexibleSearchService");
SimpleCMSComponentModel simpleCmsComponent = flexibleSearchService.search("select {pk} from {SimpleCMSComponent} where {pk} ='8796093056060'").getResult().get(0);
println(simpleCmsComponent.getUid())
I believe though that the best practice in case of CMS Components is to use their IDs instead of PK.

Related

How to select only needed fields of objects?

I am using the Pimcore API to fetch objects.
$myObjects = new Object\MyObject\Listing();
$myObjects->load();
$myObjects->getObjects();
Works as expected. Now I want to select only a specific field of my objects, e.g. the name field.
How can I tell Pimcore to select only fields that I want? Is it even possibile through the API or do I need to use custom SQL? If so, how can I do that?
Best regards
The pimcore listing is always returning the complete set of objects matching your listing condition...
If you want a fast and easy way to only select one field of your object, I recommend to use the pimcore db class:
$db = \Pimcore\Db::get();
$fieldsArray = $db->fetchCol("SELECT `YOUR_FIELD` FROM `object_query_CLASS-ID`");
This will return you an array width all 'YOUR_FIELD' values from the object query table of your class.
To get the class ID for your query dynamically your should use:
$classId = \Pimcore\Model\Object\MyObject::classId();
Edit:
To get more than one field column, you need to use 'fetchAll' instead of 'fetchCol':
$fieldsArray = $db->fetchAll("SELECT `YOUR_FIELD`, `YOUR_FIELD_2` FROM `object_query_CLASS-ID`");

Is it possible to create a cross-database query with ServiceStack ORMLite?

Pretty much summed up in the title.
Trying to hit a table in one database and join it to a table in another database on the same server.
I would have assumed an attribute for Database that I could decorate the POCO with, but do not see one that would be appropriate.
Currently using this syntax:
var result = db.Select<Model.Dto>(
db.From<Data.Dto1>()
.Join<Data.Dto2>(d1, d2) => d1.Id == d2.Id));
There's no specific attribute for specifying an external database but in RDBMS's that support cross-database queries you should be able to use the [Schema] attribute, e.g:
[Schema("Server1.Database1.dbo")]
public class Dto { ... }

Read a table from Kentico database which was not declared as 'custom table'

My question is pretty simple. I am working on Kentico 9 with its SQL Server database which contains several tables which had been added directly from the SQL Management Studio by an external contractor. The fact is that those tables are being used to store custom content which will be displayed for a site, but, in the code they don't have the code for making queries. I mean, they don't have Info and Provider classes.
https://docs.kentico.com/display/K82/Retrieving+database+data+using+ObjectQuery+API
According with this, all tables into the Kentico database can be accessed by invoking methods on these classes, but I don't have it this time.
Something like this, it will not work if I use my table name:
var user = UserInfoProvider.GetUserInfo("administrator");
var items = CustomTableItemProvider.GetItems("MyTable")
.TopN(10)
.WhereEquals("ItemCreatedBy", user.UserID)
.OrderBy("ItemCreatedWhen");
My question is:
can I query any table by its name?
One last thing:
I cannot declared those table as "custom table" because it seems to be a bug in the CMS.
Or you can pull data using your own SQL query:
var ds = ConnectionHelper.ExecuteQuery("select ....", null, QueryTypeEnum.SQLQuery);
Nevertheless I would recommend to create a custom class inside a custom module (much more robust than custom tables) instead and use the generated Info and InfoProvider classes to get and manipulate data.
I think an object has to be registered within the system (created through Kentico UI or API) in order to be pulled from DB with object query.
So I'd choose one of the following options:
Use Entity Framework or something similar to work with that data
Create appropriate custom tables or even custom module and push data there. Not sure why you can't create a custom table... What is an error you're getting?
If you need to present data on the UI only (without processing on the back end) - use just custom queries
Hope this helps.
If you are accessing in code then you could do it the good old fashioned way. If you want to pull data from the database to display on the website you could also do so by creating a custom query and using a transformation to display the fields, then use a repeater on the page to display the transformed data. Alternatively you can use a SQL datasource with a basic repeater, but you still have to create a transformation to display the data. Both methods allow you to access the data in the tables from within the CMS UI, no need to touch any code behind.
If your objective is to read data from these database tables to transform on webpage e.g. using CMS Repeater webpart, you can simply create custom query(s) in Kentico itself and load data using it. You can find the detail here on how to create custom custom queries and load data using it.
On the other hand you can also write your custom classes and define the custom methods where you can pull data using your own SQL query like this:
var ds = ConnectionHelper.ExecuteQuery("select ....", null, QueryTypeEnum.SQLQuery);
Lastly I don't think there should be any issue to create custom table instead of those direct DB tables, only thing we have to ensure code name of custom table should be unique means don't try to use exact same name because it'll cause exception due to same table name already exist in DB. You can please share exception you getting while creating custom table so that I can help you out further.

Azure Table Storage Projection Query and Not Implemented Exception

I have a Person class that I save to a table in Azure Table Storage.
I want to query it with one of the following queries:
var query = from getThis in _serviceContext.CreateQuery<PersonForSearch>(_tableName)
where getThis.Name.Contains(searchTerm)
select new Person
{
PartitionKey = getThis.PartitionKey,
RowKey = getThis.RowKey,
Name = getThis.Name
};
OR
CloudTableQuery<Person> query =
(from getThis in _serviceContext.CreateQuery<Person>(_tableName)
where getThis.Name.Contains(searchTerm)
select getThis).AsTableServiceQuery<Person>();
With either one, I get the following error, thrown on the foreach loop I use to loop through the results of the query:
NotImplemented
The requested operation is not implemented on the specified resource.
I thought that perhaps this resulted from the fact that my Person model does not inherit from TableServiceEntity (I refuse to introduce that coupling - so I decorated it with this attribute instead: [DataServiceKey("PartitionKey", "RowKey")] and manually gave it a PartitionKey and RowKey property.
So I tried to create an entity that DID inherit from TableServiceEntity, which would allow me to query this table (as you can see from the queries, the only property I'm worried about is Name).
This new entity is as follows:
class PersonForSearch : TableServiceEntity
{
public string Name { get; set; }
}
However, this hasn't solved the problem. Is this error talking about some other resource than the class I'm using in my query?
There are a two issues here:
1) Azure Table Storage does not support Contains() method. This is the reason you're getting Not Implemented exception. ATS does support string.Compare() for any range-type operations on strings
2) In order to retrieve the data effectively, you can only search on PartitionKey or on PartitionKey/RowKey combination. Any other query will result in either errors or the download of the full table into client's memory (can't remember which one). If your table is small, download it into memory completely by dropping the 'where' clause and afterwards use Linq for Objects to query however you like. If it is large, find a way to compare against PartitionKey or PartitionKey/RowKey fields
If I'm understanding what you're trying to do correctly, is that you're trying to do a partial string-search through employee table. Overall, ATS is not a very good solution for doing string-based searches (unless these are "starts with" searches on PartitionKey or PartitionKey/RowKey fields). I'd like to highly recommend Lucene.NET for doing text-based searches in the cloud. There is an Azure Directory API for Lucene.NET available as well. Or switch to SQL Azure
HTH

ExecuteJoinedDataSet but with Where()

I did some searching and see that ExecuteJoinedDataSet will not work with the Where clause in 2.1. If I want to query a table with WHERE, but want the FK objects values to be bindable is the easiest way to just create a custom class(my table has tons of FK references).
Could you give us an example of what kind of query you are trying to write? If you are just trying to return a DataTable without creating a custom class just write your query and use the ExecuteReader which Returns an IDataReader. The IDataReader is bindable and if you need more you can just load it into a DataTable.

Resources