Saturday, January 23, 2016

Websphere Commerce SOLR tips


Introduction 

Websphere Commerce uses apache solr which is a fast open source java search server for its searches. We know that the product and other data are stored in database. DB queries are heavy and performance intensive. Hence we can't keep on querying the DB to get the results for every search. 


As a solution for this and to make our searches fast, commerce introduced Solr.  Solr is able to achieve fast search responses because instead of searching the text directly, it searches an index.  Solr stores this index in a directory called index in the data directory. Apart from just being fast, Solr provides the ability to change the relevancy of search result. This means by changing certain parameters we can improvise the order in which the search results appear.

For example if somebody search for "pepsi", ideally pepsi drink must come in the top. 7up is also a product of pepsi and it will have the word "pepsi" in the manufacturer name. In this scenario we can say that a match for search term in product name is more relevant than a match in manufacturer name. This way we can make sure that the correct product is displayed on the top. 7up will still be there in the search result but with a lesser relevancy. Also boost the products we want by changing the boost factor, change the sorting options, filtering specific products/categories from results and much more can be done using solr.

Commerce reindexing
Commerce reindexing is the process of indexing the data from DB in Solr. It consists of two processes. 

Pre-process: Preprocess the data to be stored/indexed in solr and save it into temporary tables.
Build-index: Indexes the data in temp table to solr.

Important files for reindexing 
Solrconfig.xml : This file has the configurations of solr like connection time out, replication handling, max connections etc.
Schema.xml : This file has the definition of the solr fields.
pre-process xmls : These xmls will have the sqls to create the temporary table and populate them as we need.
wc-data-config.xml : This has the query to get the data to populate the solr indexes and also have the mapping between the temporary table name to the solr field name.

SOLR Queries
We save fields in SOLR in a specific core. Mostly for product searches we use MC_10001_CatalogEntry_en_US (where 10001 is the master catalog of the store).  For an easy analogy I am comparing SQL queries to SOLR queries.

If we want to get all the products from DB in a query we will write it as 
SELECT * FROM CATENTRY;

The corresponding solr implementation would be as below

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=*:*

q parameter is the main query of the request which is equivalent to the search term. Here we are passing q as * which means the query will fetch every doc in solr.

Now if we want to get all the product data which has got "milk" in the product name we will use the DB query 

SELECT CT.* FROM CATENTRY CT, CATENTDESC CD WHERE CD.CATENTRY_ID = CT.CATENTRY_ID AND LOWER(CD.NAME ) LIKE '%milk%'
In Solr we can write the same query as below

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=milk&fq=name:milk
Here "fq" stands for the filter query. Filter queries are used to add conditions to solr queries. CD.NAME in the above DB query is indexed as field "name" in Solr. So the solr query means, get all the details from solr which has the term milk in any of the fields and filter the results such that the results  has "milk" in the field "name". So all the other results which might have "milk" in any other fields are omitted.

Say now we want to select all the search for milk which are has milk in product name and are in Dairy category. The DB query will look like below. You can see that the query is becoming bigger and messier
SELECT CT.* FROM CATENTRY CT, CATENTDESC CD , CATGPENREL CG, CATGRPDESC CGD WHERE CD.CATENTRY_ID = CT.CATENTRY_ID 
AND CG.CATENTRY_ID = CT.CATENTRY_ID
AND CGD.CATGROUP_ID = CG.CATGROUP_ID
AND LOWER(CD.NAME ) LIKE '%milk%'  
AND CGD.NAME LIKE '%Dairy%'

The solr query for the same would look like
http://localhost/solr/MC_10001_CatalogEntry_en_US/selectq=*&fq=name:milk&fq=categoryname:Dairy
Note : categoryname is the solr field corresponding to DB category name column
It is just an addition another filter query and bang you get the results..!!

Let us make a slight modification to fetch the products in diary as well as fresh category. The sql will be
SELECT CT.* FROM CATENTRY CT, CATENTDESC CD , CATGPENREL CG, CATGRPDESC CGD WHERE CD.CATENTRY_ID = CT.CATENTRY_ID 
AND CG.CATENTRY_ID = CT.CATENTRY_ID
AND CGD.CATGROUP_ID = CG.CATGROUP_ID
AND LOWER(CD.NAME ) LIKE '%milk%'  
AND (CGD.NAME LIKE '%Dairy%' OR CGD.NAME LIKE '%Fresh%')

Let us get help from solr, the query would be almost similar to above with a slight change

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=*&fq=name:milk&fq=categoryname:(Dairy+Fresh)

Say now we want to get all the above results but don't want products which are from a specific manufacturer (say RanjithsMilk). DB query would look like
SELECT CT.* FROM CATENTRY CT, CATENTDESC CD , CATGPENREL CG, CATGRPDESC CGD WHERE CD.CATENTRY_ID = CT.CATENTRY_ID 
AND CG.CATENTRY_ID = CT.CATENTRY_ID
AND CGD.CATGROUP_ID = CG.CATGROUP_ID
AND LOWER(CD.NAME ) LIKE '%milk%'  
AND (CGD.NAME LIKE '%Dairy%' OR CGD.NAME LIKE '%Fresh%')
AND CT.MFNAME NOT LIKE '%RanjithsMilk%'
This is really messy as we can see couple of like and one not like in the same query. So if make a query for the above requirement in Solr, it would look like below

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=*&fq=name:milk&fq=categoryname:(Dairy+Fresh)&fq=-mfName:RanjithsMilk

Note : mfName corresponds to the DB column CT.MFNAME and " - " corresponds to removing the results from the query

Yes it is just another filter query.. !!!!!
Now if we look at the SQL and the solr query , it is pretty evident that the the solr queries are really easy to write and is fast to execute. This is a very simple example. An original search will have much more stuffs and then SOLR will be really handy.

Paginated results : we can use start (start index of the results) and rows (number of rows to be fetched) parameters to get paginated results. The below query will fetch the first five results from the response.

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=*&fq=name:milk&fq=categoryname:(Dairy+Fresh)&fq=-mfName:Coles&start=0&rows=5

Field lists : By using fl parameter we can specify the fields that we need in the response through which we can get rid of unused data. The below query will return only name and category name in the results.

http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=*&fq=name:milk&fq=categoryname:(Dairy+Fresh)&fq=-mfName:Coles&start=0&rows=5&fl=name,categoryname


These are some of the basic tips for querying solr. There are much more things we can do and it can be covered in a different post.






Sunday, December 13, 2015

Changing the http and https port numbers in WCS7

Changing the http and https port numbers in WCS7

As we all know, the default port number configured in WCS for http is 80 and https is 443. In many of the PCs provided by organizations these ports will already be in use and hence we will have to change the default values. Below are the steps to change the port numbers in commerce.


1. Change the port number in WAS console
In WAS we need to change the port numbers in three places.
  •    Open WAS console and go to Environment-->Virtual hosts --> Change port numbers for all the virtual hosts
  •    Go to servers--> Server Types-->Websphere application servers -->  click server1 --> click Ports on the right hand side --> Change the ports appropriately
  •     If you are on or above FEP7 you need to change the search url and search port. Go to Environment --> Naming --> Name space bindings. change the port numbers for com.ibm.commerce.foundation.server.services.search.url and com.ibm.commerce.foundation.server.services.search.port 
2. DB changes

Change the port numbers in SRCHCONF and SRCHCONFEXT tables. updating tables will require a restart to reflect the changes

3. Change the port number for solr url in wc-search.xml.
  •            In RAD navigate to WC-->xml-->config-->com.ibm.commerce.catalog.ext-->wc-search.xml. Locate  "<_config:common-http URL". Add port number in the url it must look like        "http://localhost:81/solr/"
  •            Navigate to WC-->xml-->config-->com.ibm.commerce.catalog.fep-->wc-search.xml. Make the same change as above there as well.
The same changes need to be done in wc-search.xml in Search project as well.


All these changes requires a restart to reflect.
  

Thursday, October 15, 2015

Resetting and Configuring development environment for Websphere Commerce

A clean development environment is one of the first thing a developer must have. If the workspace is having a lot of errors, warnings, unwanted files etc, it is pretty tough to code and troubleshoot. This post explores a way to set up a proper developement environment for Websphere Commerce.

1. Install WCS base product. 
You can find the instructions in the below link

Installing Websphere Commerce

2. Install the latest available fix pack. 
The fix pack contains the fixes for bugs in the product and it is really important that we keep the FP level updated. Also FPs will be a prerequisite for the feature packs. For example : to install FEP8, we need FP9.
Installing Websphere Commerce Fix Packs

3. Install the feature pack. 
A feature pack contains new features added to the product. This differs from fix packs as it doesn't contain fixes to the base commerce product. After installing we have to enable the features one by one. Foundation, management-center, store-enhancements, social-commerce, content-version, sterling-integration, location-services are the features available.
Installing Websphere Commerce Feature Packs

4. Reset the development environment to bootstrap data.
Once the installations are complete the workspace will have a lot of stores(like Madisons,consumer direct, Elite etc) published and will contain the assets(jsp, js, properties files etc) for all of them. Usually we would require only one store and hence all these assets are not used. Also the DB would be populated with a lot of data for all these stores which we are not interested in. The below steps needs to be carried out in order reset the environment.

Here an assumption is made that we switch from derby to DB2 database. Steps would be similar for Oracle as well.

4.1. Execute restoreDefault.bat
This utility will restore the development environment to bootstrap data.It will internally run setup.bat as well and will make sure that you have the default setup.
Make sure the test server is stopped and RAD is closed. Navigate to WC_InstlDir\bin and execute restoreDefault.bat force.

4.2. Execute setdbtype.bat
This is required only if you are changing the developer DB from derby to DB2 or Oracle. Changing dev DB does not carry over any schema customization or custom data to the new DB. Below is a sample of command to be executed for DB2
Example: C:\IBM\WCDE_ENT70\bin>setdbtype.bat db2 C:\IBM\SQLLIB mall db2admin passw0rd db2admin passw0rd createdb

4.3. Execute resetstores.bat
This utility resets the Stores web module in the workspace to its original configuratiojn. All published and pre-published store assets are deleted from the workspace. Navigate toWC_InstlDir\bin and execute resetstores.bat

4.4. Execute updatedb.bat
This updates the WCS database to the latest fix pack level that is installed in the system. Navigate to WC_InstlDir\bin and execute updatedb.bat
 Example :
C:\IBM\WCDE_ENT70\bin\updatedb.bat db2 database_name database_user_name database_user_password

4.5. Enable features
Even though you have installed a feature back, restoreDefault utility would have disabled all the features and hence we have to re-enable them. the below commands can be used for the same.
Navigate toWC_InstlDir\bin  
enableFeature.bat -DfeatureName=foundation
enableFeature.bat -DfeatureName=management-center
enableFeature.bat -DfeatureName=content-version
enableFeature.bat -DfeatureName=store-enhancements
enableFeature.bat -DfeatureName=location-services

OR
To enable all the features in one go run the below script
enableFeature.bat -DfeatureName=ALL
 
enabling features

5. Build and re-publish the application
Do a clean and build (build open lazlo project as well). Start the server and re-publish the application.

6. Publish the store you need. 
The below link has the step by step description on how to publish an extended site

7. Configure search
To configure search feature for our store, we need to perform the below steps. On a very high level this includes setting up the solr indexes, per-populating the data in to temp tables and populating Solr indexes.

7.1 Setting up search index
SetupSearchIndex utility configures the Solr cores by creating all core instances for the specified master catalog. Ensure the test server is stopped.
Navigate to WC_InstlDir\components\foundation\subcomponents\search\bin and execute setupSearchIndex.bat

Example ; setupSearchIndex.bat –masterCatalogId 10001 –solrhome C:\IBM\WCDE_ENT70\search\solr\home  

7.2. Pre-process search index data
di-preprocess utility extracts and flattens websphere commerce data and then outputs it to a set of temporary tables. The data in these temp tables are then used to populate Solr. Ensure that the server is stopped. Navigate to  WC_InstlDir\bin and execute di-preprocess.bat
Example : di-preprocess.bat C:\IBM\WCDE_ENT70\search\pre-processConfig\MC_10001\DB2 

7.3. Build the search index
 The build index utility fetches the data from temporary tables and populates the Solr indexes. It uses Data Import Handler (DIH) for this. We can either build partially through delta updates or can do a full build as well. Navigate to  WC_InstlDir\bin and execute di-buildindex.bat
Example : di-buildindex.bat –masterCatalogId 10001


Note : If you are not planning to switch the DB and go ahead with derby itself, execute restoreDefault, resetStores, resetdb, setdbtype, updatedb and enablfeatures utility in the order respectively.





 

Cross transactional cache invalidation across WCS and Search applications

Introduction Cache invalidation is one of the key and tedious part of software development. It is really important that we purge the inval...