Wednesday, November 28, 2018

Endeca Indexing Process

Introduction

While working on different Endeca implementations, we come across scenarios where the indexed data does not contain the latest changes or sometimes gets corrupted. Apart from these, there is high possibility of encountering indexing failures. While some indexing failures does not impact the Dgraph whereas others result in failed Dgraphs, thus bringing down the Endeca servers.
In many applications, re-indexing data would contain the following steps
1. Identify root cause of data failure and fix this in data import process.
2. Run the data import process. Both ATG and non-ATG applications would consume considerable amount of time during this stage.
3. Initiate BCC deployment
4. Trigger Endeca indexing process.

There are times where data import fix would consume numerous days with stale index data residing on the production environment provided that Dgraph failures are backed up with successful generations. This makes monitoring of generated data consumed by Endeca indexing process super critical.

Endeca Validator Component

Based on CAS recordstore APIs, we can create custom components which can run just before EndecaScriptService and provide essential checks before indexing the raw data from CAS record stores.

We can customize this component to execute the following items before handing over the control to EndecaScriptService
1. Check the count of records being processed. Minimum threshold can be used to keep a track of failed records and cancelling EndecaScriptService if this number is huge.
2. This component can be further enhanced by making use of record store APIs to inspect and validate each and every Endeca records for troubleshooting issues. This is similar to the implementation done in the following link.
http://www.ateam-oracle.com/debugging-cas-with-the-endeca-recordstore-inspector/
3. Like the way, we inspect product catalog using ATG Dyn Admin, this component can be customized to provide CAS record data lookup based on Endeca.Id

Understanding and Debugging Endeca Query Results

Introduction
The word "Why" holds the key to many inventions and better understanding in the scientific community. Perhaps this the reason "Why and How" are also used in our technical community. This blog generally focus on the understanding and debugging endeca queries. It gives an opportunity to the developers on "Why" the result is "A" instead of "B" and "How" this can be changed. Understanding the "Why Match" feature enables the developers to interpret the root level approach to a technical solution.

1. About the Why Match feature
The Why Match functionality allows an application developer to debug queries by examining which property value of a record matched a record search query and why it matched.
With Why Match enabled in an application, records returned as part of a record search query are augmented with extra dynamically generated properties that provide information about which record properties were involved in search matching.


a.) Enabling Why Match
You enable Why Match on a per-query basis using the Nx (Navigation Search Options) query parameter.No Developer Studio configuration or Dgraph flags are required to enable this feature.
However, because Why Match applies only to record search navigation requests, dynamically-generated properties only appear in records that are the result of a record search


b.) Why Match API
The MDEX Engine returns match information for each record as a DGraph.WhyMatch property in the search results.
The following code samples show how to extract and display the DGraph.WhyMatch property from a record.


Java example
// Retrieve properties from record
PropertyMap propsMap = rec.getProperties();
// Get the WhyMatch property value
String wm = (String) propsMap.get("DGraph.WhyMatch");
// Display the WM value if one exists
if (wm != null) {
%>This record matched on <%= wm %>
<%
}


c.) Why Match performance impact
The response times for MDEX Engine requests that include Why Match properties are more expensive than requests without this feature. The performance cost increases as the number of records returned with the DGraph.WhyMatch property increases.

This feature is intended for development environments to record matching. The feature is not intended for production environments and is not particularly optimized for performance.



2. About the Word Interpretation feature
The Word Interpretation feature reports word or phrase substitutions made during text search
processing.
The Word Interpretation feature is particularly useful for highlighting variants of search keywords that appear in displayed search results. These variants may result from stemming, thesaurus expansion, or spelling correction.


a.) Implementing Word Interpretation
The --wordinterp flag to the Dgraph command must be set to enable the Word Interpretation
feature.
The Word Interpretation feature does not require any work in Developer Studio. There are no Dgidx flags necessary to enable this feature, nor are there any MDEX Engine URL query parameters.


b.) Word Interpretation API methods
The MDEX Engine returns word interpretation match information in ESearchReport objects.
This word interpretation information is useful for highlighting or informing users about query expansion.
The Java ESearchReport.getWordInterps() method return the set of word interpretations used in the current text search. Each word interpretation is a key/value pair corresponding to the original search term and its interpretation by the MDEX Engine.


Java example
// Get the Map of ESearchReport objects
Map recSrchRpts = nav.getESearchReports();
if (recSrchRpts.size() > 0) {
// Get the user’s search key
String searchKey = request.getParameter("Ntk");
if (searchKey != null) {
if (recSrchRpts.containsKey(searchKey)) {
// Get the ERecSearchReport for the search key
ESearchReport searchReport = (ESearchReport)rec¬
SrchRpts.get(searchKey);
// Get the PropertyMap of word interpretations
PropertyMap wordMap = searchReport.getWordInterps();
// Get property iterator
Iterator props = wordMap.entrySet().iterator();
// Loop over properties
while (props.hasNext()) {
// Get individual property
Property prop = (Property)props.next();
String propKey = (String)prop.getKey();
String propVal = (String)prop.getValue();
// Display word interpretation information
%><tr>
<td>Original term: <%= propKey %></td>
<td>Interpreted as: <%= propVal %></td>
</tr><%
}
}
}
}
3. About the Why Rank feature
The Why Rank feature returns information that describes which relevance ranking modules were evaluated during a query and describes how query results were ranked. This information allows an application developer to debug relevance ranking behavior.


With Why Rank enabled in an application, the MDEX Engine returns records that are augmented with additional dynamically generated properties. The MDEX Engine also a returns summary information (in a Supplement object) about relevance ranking for a query. The properties provide information that describe which relevance ranking modules ordered the results and indicate why a particular record was ranked in the way that it was.


a.) Enabling Why Rank
You enable Why Rank on a per-query basis using the Nx (Navigation Search Options) query parameter or the Dx (Dimension Search Options) query parameter. No Developer Studio configuration or Dgraph flags are required to enable this feature.


b.) Why Rank API
The MDEX Engine returns relevance ranking information as a DGraph.WhyRank property on each record in the search results. The MDEX Engine also returns summary information for all record results in a Supplement object.
Java example
// Retrieve properties from record
PropertyMap propsMap = rec.getProperties();
// Get the WhyRank property value
String wr = (String) propsMap.get("DGraph.WhyRank");
// Display the WR value if one exists
if (wr != null) {
%>This record was ranked by <%= wr %>
<%
}
Here is an example of a query and a DGraph.WhyRank property from a record in the result set.
Suppose there is a query submitted to an MDEX Engine using the following query parameters:
N=0&Ntk=NoEssay&Ntt=one+two&Ntx=rel+phrase(considerFieldRanks)&Nx=whyrank.
The query produces a result set where one of the records contains the following DGraph.WhyRank property:
<Property Key="DGraph.WhyRank" Value="[ { "phrase" : { "evaluationTime" :
"0", "stratumRank" : "20", "stratumDesc" : "phrase match", "rankedField" :
"English" }} ]">


c.) Why Rank performance impact
The response times for MDEX Engine requests that include Why Rank properties are more expensive than requests without this feature. The performance cost increases as the number of records returned with the DGraph.WhyRank property increases.
This feature is intended for development environments to troubleshoot relevance ranking. The feature is not intended for production environments and is not particularly optimized for performance.


4. About the Why Precedence Rule Fired feature
The Why Precedence Rule Fired feature returns information that explains why a precedence rule fired.This information allows an application developer to debug how dimensions are displayed using precedence rules.
With the feature enabled in an application, the root dimension values that the MDEX Engine returns are augmented with additional dynamically generated properties. The properties provide information that describe how the precedence rule was triggered (explicitly or implicitly), which dimension ID and name triggered the precedence rule, and the type of precedence rule (standard, leaf, or default).

a.) Enabling Why Precedence Rule Fired

You enable Why Precedence Rule Fired on a per-query basis using the Nx (Navigation Search Options) query parameter. No Developer Studio configuration or Dgraph flags are required to enable this feature.

b.) Why Precedence Rule Fired API
The MDEX Engine returns information about why a precedence rule fired as a DGraph.WhyPrecedenceRuleFired property on each root dimension value.
The following code samples show how to extract and display the DGraph.WhyPrecedenceRuleFired property from a root dimension value.


Java example
// Retrieve the results object.
Navigation result = results.getNavigation();
// Retrieve the refinements.
DimensionList l = result.getRefinementDimensions();

// Retrieve the dimension with ID 80000.
Dimension d = l.getDimension(800000);
// Retrieve the root dval for the dimension.
DimVal root = d.getRoot();
PropertyMap propsMap = root.getProperties();
// Get the WhyPrecedenceRuleFired property value
String wprf = (String) propsMap.get("DGraph.WhyPrecedenceRuleFired");
// Display the value if one exists
if (wprf != null) {
//Do something
}


c.) Why Precedence Rule Fired property format
The DGraph.WhyPrecedenceRuleFired property value has a multi-part format that is made up of a list of trigger reasons and trigger values that were evaluated for each precedence rule.
The DGraph.WhyPrecedenceRuleFired property is returned as a JSON object with the following format:
[
{ "triggerReason" : "<Reason>", "triggerDimensionValues" : ["<DimensionID>,
... "], "ruleType" : "<Type>", "sourceDimension" : "<DimensionName>",
"sourceDimensionValue" : "<DimensionID>" },
...
]


d.) Performance impact of Why Precedence Rule Fired
The Why Precedence Rule Fired feature is intended for a production environment.The response times for MDEX Engine requests that include DGraph.WhyPrecedenceRuleFired properties are slightly more expensive than requests without this feature. In general, the feature adds performance throughput costs that are typically observed to be less than 5%.

Thursday, September 14, 2017

ATG Shipping Groups, methods and calculators

Adding shipping information to shopping carts involves the following sub-processes:

1) Creating a list of shipping groups for potential use in the current order
2) Specifying the shipping groups to use with the current order
3) Selecting the shipping methods, such as Ground or Next Day, for the order’s shipping groups 


What is Shipping Group?
A ShippingGroup contains information on the shipping address and delivery method for a group of commerce items. 

By default, a new Order has one defaultShippingGroup. As items are added to the Order, these items automatically become part of the default ShippingGroup. Once a second ShippingGroup is added to theOrder, all the items in the Order are removed from the default ShippingGroup and must be explicitly added to one of two shipping groups. 
  
How to create new Shipping Groups?
You can create a list of shipping groups for potential use in an Order in one of two ways: 
  • from information gathered from the user via forms

  • from information stored in the user’s profile
 Below two form handlers allow user to add new shipping groups   
  • /atg/commerce/order/purchase/CreateHardgoodShippingGroupFormHandler
  • /atg/commerce/order/purchase/CreateElectronicShippingGroupFormHandler
 Both extends PurchaseProcessFormHandler 

How to add Shipping Group to an Order?
Steps:
1) Create Shipping Group
2) Make any changes to the Shipping Group, such as setting the address
3) Add the Shipping Group to the Order


 Here is the code snippet:
// Get a reference to the OrderManager 
OrderManager orderManager = (OrderManager)   request.resolveName("/atg/commerce/order/OrderManager");  
// Create the ShippingGroup 
ShippingGroup shippingGroup shippingGroupManager.createShippingGroup(); 
// Add the ShippingGroup to the Order shippingGroup.addShippingGroupToOrder(pOrder, shippingGroup); 

How to find available Shipping methods for a particular Shipping Group? 
Use droplet  /atg/commerce/pricing/AvailableShippingMethods


How to initiate Shipping group from Profile? 
Use droplet /atg/commerce/order/purchase/ShippingGroupDroplet 
  
What is Shipping method?  
Each Shipping method is represented by ShippingCalculator component class.

Shipping methods examples are:
  • Ground
  • 2 day delivery
  • Overnight
  • Calculate Shipping price based on couriers web service
  • etc...
Different types of Shipping calculators are:
  • FixedPriceShippingCalculator - Flat rate for shipping
            Ex: Ground shipping is always $15
  • PriceRangeShippingCalculator - Define shipping price based price range
             Ex: $0 - $50  ($5)
                   $51 - $100  ($10)
                   $101 - $1000  (FREE)
  • WeightRangeShippingCalculator - Weight Property added at SKU level and price set based on weight
  • PropertyRangeShippingCalculator - Shipping price decided Based on SKU property
          Ex: Volume
    How to Filter Shipping methods?
    In few scenarios, All shipping methods should not be available. To limit shipping methods developer can sub-class Shipping calculator and override the getAvailableMethods().

    Ex: Courier shipping not allowed for PO boxes

    How to write custom shipping calculator?
    Here are the steps:
    1. Create a new custom calculator component 
    /com/commerce/shipping/FixedPriceServiceCaclulator.properties 
    $class=com.xxx.commerce.pricing.calculators.FixedPriceShippingCalculator
    # name of shipping method
    shippingMethod=DEMO
    # costs 
    amount=10.0

    2. Create a custom Java class and this should extends the shippingCalculatorImpl class
    ShippingCalculatorImpl class have two method for override.
    1.getAmount()  - calculate the shipping price

    2.getAvailableMethods()  - Used to restrict your custom shipping method

    public class FixedPriceShippingCalculator extends ShippingCalculatorImpl { 

    protected double getAmount(Order order, ShippingPriceInfo priceQuote, ShippingGroup shippingGroup, RepositoryItem pricingModel, Locale locale, RepositoryItem profile, Map extraParameters) throws PricingException { }

    public void getAvailableMethods(List pMethods, ShippingGroup pShippingGroup, RepositoryItem pPricingModel, Locale pLocale, RepositoryItem pProfile, Map pExtraParameters) throws PricingException {
    }
    }
    3. Add the shipping calculator to Shipping Engine
    /atg/commerce/pricing/ShippingPricingEngine.properties 
    preCalculators+=/com/commerce/shipping/FixedPriceServiceCaclulator

    Adding New Shipping Method in ATG


    1.      Create the Shipping Calculator
    /com/commerce/shipping/FedEx.properties
    $class=atg.commerce.pricing.FixedPriceShippingCalculator
    # name of shipping method
    shippingMethod=FedEx
    # costs
    amount=10.0
    # pricing tools
    pricingTools=/atg/commerce/pricing/PricingTools

    2.      Add the shipping calculator to Shipping Engine
    /atg/commerce/pricing/ShippingPricingEngine.properties

    preCalculators+=/com/commerce/shipping/FedEx

    Wednesday, November 9, 2016

    add a custom property of order item to the CSC order search panel

    add a custom property of order item to the CSC order search panel...

    Following are the changes we have done...

    1 – Added TAN column to dcsppx_order table

    2 – CommerceModule/config/atg/commerce/order/orderrepository.xml
    Modified to add TAN a persistent String property

    3 –  CommerceModule/config/atg/commerce/search/order-output-config.xml
    added following line
    <property name="tan" type="string" store-as-meta-index="true" output-name="tan"/>

    4 –  CSCModule/src/com/uscc/commerce/csr/search/CustomOrderSearchTreeQueryFormHandler.java
    Extended OrderSearchTreeQueryFormHandler to add TAN property and its getter setter.

    5 –  CSCModule/config/atg/commerce/custsvc/order/OrderSearchTreeQueryFormHandler.properties
    Modified to include TAN property

    6 –  CSCModule/j2ee-apps/CSCModule/CSCModule.war/include/order/orderSearchUIFragment.jsp
    Modified to add a new textbox for TAN

    7 –  CSCModule/j2ee-apps/CSCModule/CSCModule.war/panels/order/search.jsp
    Added JS changes to set name, operator, value fields