Skip to Content

You can find the series and project from Real-time sentiment rating of movies on SAP HANA (part 6) – wrap-up and looking ahead

Intro

Hi everyone, welcome to the series again. We’re now in the second half of the series. Hope you’ve enjoyed the previous three blogs including

Real-time sentiment rating of movies on SAP HANA (part 1) – create schema and tables

Real-time sentiment rating of movies on SAP HANA (part 2) – data preparation

Real-time sentiment rating of movies on SAP HANA (part 3) – text analysis and modeling

In the above three blogs, we’ve already finished data preparation and sentiment analysis, in addition we’ve also created two information views which will be consumed in the following two blogs. Now, it’s time for UI. In this blog let’s first take a look at SAP HANA info access and build our first smart application based on this super cool feature!

What is SAP HANA info access?

Maybe it’s the first time you heard SAP HANA info access, never mind. Let’s first have a look at it. You can find the detailed introduction and its usage from  Building Search UIs with SAP HANA Info Access – SAP HANA Developer Guide – SAP Library, so I won’t show the details here. I just highlight something important for you.

“The SAP HANA info access HTTP service wraps search SQL queries and exposes them through an HTTP interface. The service operates on one SAP HANA attribute view at a time and makes use of the indexed and analysed texts joined in that view.”

22.PNG

First of all you can find the above definition and architecture diagram of SAP HANA info access from SAP HANA Info Access Architecture – SAP HANA Developer Guide – SAP Library. As you can see, there are four layers including attribute views and Info Access HTTP Service on the SAP HANA side, while SINA and Info Access Dev Toolkit for HTML5 on the UI side. With SAP HANA info access, you do not need to care the server-side search logic and you can just focus on the UI stuff. So, why not use this awesome feature to build our sentiment app? In our smart app, we’ll just use the attribute view which is already defined in Real-time sentiment rating of movies on SAP HANA (part 3) – text analysis and modeling and the Info Access Dev Toolkit for HTML5 at the top layer for simplicity. I’ll show you how simple but powerful it is in this blog. 😉

There is still something you need to notice. Make sure you’ve finished the following before you start your journey with SAP HANA info access.

  1. Import the delivery unit “HCO_INA_SERVICE.tgz” from your SAP HANA server, since this DU is not included in the default installed DU list, i.e., when you install SAP HANA server, it is not automatically installed like the SAPUI5 DU.
  2. Download the delivery unit “HCO_INA_UITOOLKIT.tgz” from SAP Software Download Center to your desktop/laptop and import the DU from the client side.
  3. Assign this role “sap.bc.ina.service.v2.userRole::INA_USER” to the user whom you want to use SAP HANA info access.

In addition, I highly recommend you to play with the SAP HANA info access demo in SHINE (section 9.10) first, since you can have a basic idea & look and feel about SAP HANA info access from this demo. Visit http://<myServer>:<XS_Port>/sap/hana/democontent/epm/fulltextsearch/ui/search.html after you import SHINE and generate data. Besides, you can also have a look at its source code, as our smart app is based on it.

/wp-content/uploads/2014/11/23_578043.png

Info Access Dev Toolkit for HTML5

Since we’ve already preapred our attribute view “AT_TWEETS.attributeview” in Real-time sentiment rating of movies on SAP HANA (part 3) – text analysis and modeling, what we need to do in this blog is more related with the front-end stuff such as HTML, CSS and JavaScript. Now let me show you the most important search.html file which we will visit directly in our browser. If you’ve read the source code of the SINA demo in SHINE, you’ll be familiar with it. Here I just want to mention some key points from top to bottom. (I just found the syntax highlighting does not work on SCN today, so the below code may look ugly. Sorry for that. 🙁 )

1. You need to include the following script when you use the info access development toolkit.


<script data-main="/sap/bc/ina/uitoolkit/js/main.js" src="/sap/bc/ina/uitoolkit/js/lib/require.js"></script>














2. createFulltextIndex.js is used to create full text index of the searched fields for the first time. We’ll discuss it later.

3. The following code defines the name/package/key of the attribute view.


<div data-sap-widget="workarea" data-entityset="AT_TWEETS" data-packagename="movieRating.models" data-aggregationdimension="id_counter">

4. We have 6 work area items (position from 0 to 5) in our facet pane, while there are only 3 in the SINA demo of SHINE. Besides, we have one work area item (position 6) for the result list in our content pane.

5. We have 17 work area items with the chart widget in our facet repository and the following 6 are displayed by default which seem the most important.

  • SENTIMENT BY MOVIE
  • SENTIMENT
  • TWEET SOURCE
  • TITLE
  • TOKEN
  • STUDIO

6. Except SENTIMENT BY MOVIE, for each work area item with the chart widget, you can switch between bar chart, pie chart and tag cloud for your convenience.

7. We have one work item area with the result list widget which shows the details of each MENTION and the result list is sorted by “created_at” in a descending order, i.e., you will see the most recent mention at first. Similar with the SINA demo of SHINE, we also define 3 separate result templates as follows.

  • tweet.html: Defines the template of the result in our content pane.
  • tweet_small.html: Defines the template of the result in our facet pane.
  • tweet_detail.html: Defines the template of the result in the overlay container.


search.html


<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Movie Sentiment Rating based on SINA</title>
<!-- CSS: implied media="all" -->
<!-- CSS concatenated and minified via ant build script-->
<link rel="stylesheet" type="text/css" href="search.css">
<!-- end CSS-->
<link rel="shortcut icon" href="img/favicon.png" />
<script data-main="/sap/bc/ina/uitoolkit/js/main.js" src="/sap/bc/ina/uitoolkit/js/lib/require.js"></script>
<script>
requirejs(['server/createFulltextIndex.js'], function   () {
});
</script>
<!-- create fulltext index -->
<!-- <script src="server/createFulltextIndex.js"></script> -->
</head>
<body>
    <header>
        <div data-sap-widget="header" data-title="Movie Sentiment Rating based on SINA" data-helphref="http://help.sap.com/hana/SAP_HANA_INA_Search_JavaScript_Reference_en/index.html"></div>
    </header>
    <div class="background">
    <div data-sap-widget="alert"></div>
   <div data-sap-widget="workarea" data-entityset="AT_TWEETS" data-packagename="movieRating.models" data-aggregationdimension="id_counter">
    <div class="searchnfilterframe">
    <div data-useresponseattributes="false" data-usedimensions="true" data-sap-widget="searchnfilter"></div>
    </div>
        <div class="facetPaneShadow">
          <div class="facetPane">
            <div class="facetColumn" data-children-drag-handle="header">
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="0"></div>
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="1"></div>
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="2"></div>
            </div><!-- end of the facetColumn" -->
          </div> <!--  end of facetPane -->
        </div> <!--  end of facetPaneShadow -->
      
        <div class="facetPaneShadow">
          <div class="facetPane">
            <div class="facetColumn" data-children-drag-handle="header">
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="3"></div>
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="4"></div>
                <div data-sap-widget="workareaitem" data-title="Drop here" data-target-position="5"></div>
            </div><!-- end of the facetColumn" -->
          </div> <!--  end of facetPane -->
        </div> <!--  end of facetPaneShadow -->
        <div class="contentPaneShadow">
            <div class="contentPane" data-children-drag-handle="header">
                <!-- The following div is a placeholder that will be replaced on the first time a workarea-centerable will be centered. -->
                <div data-sap-widget="workareaitem" data-iscenter="true" data-title="Drop here" data-target-position="6"></div>
            </div>
        </div>
        <div data-sap-widget="facetrepository" data-children-drag-handle="body">
      
        <div data-sap-widget="workareaitem" data-title="SENTIMENT BY MOVIE" data-source-position="0">
                        <div data-sap-widget="switchbox" data-activeindex="0">
                            <a href="javascript: void(0);" class="iconTimeline">Timeline</a>
                            <div data-sap-widget="chart" data-dimension-line="sentiment" data-dimension-x="title" data-dimension-y="$$Count$$" data-charttype="line" data-color="colored" data-toplarge=10 data-maxlabelnum="all"></div>
                            <a href="javascript:void(0)" class="iconGroupBarChartVertical">Goup Bar Chart</a>
                            <div data-sap-widget="chart" data-toplarge="25" data-topsmall="5" data-title="SENT-MOVIE-GROUPBAR" data-dimension-line="title" data-dimension-x="sentiment" data-dimension-y="$$Count$$" data-charttype="groupbar"></div>
                        </div>
                </div>
      
        <div data-sap-widget="workareaitem" data-title="SENTIMENT" data-source-position="1">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="SENTIMENT-BAR" data-dimension="sentiment" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="SENTIMENT-PIE" data-dimension="sentiment" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="SENTIMENT-TAG" data-dimension="sentiment" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET SOURCE" data-source-position="2">
                    <div data-sap-widget="switchbox" data-activeindex="0">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="SOURCE-BAR" data-dimension="tweet_source" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="SOURCE-PIE" data-dimension="tweet_source" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="SOURCE-TAG" data-dimension="tweet_source" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TITLE" data-source-position="3">
                    <div data-sap-widget="switchbox" data-activeindex="2">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TITLE-BAR" data-dimension="title" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TITLE-PIE" data-dimension="title" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TITLE-TAG" data-dimension="title" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TOKEN" data-source-position="4">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TOKEN-BAR" data-dimension="token" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TOKEN-PIE" data-dimension="token" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TOKEN-TAG" data-dimension="token" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="STUDIO" data-source-position="5">
                    <div data-sap-widget="switchbox" data-activeindex="0">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="STUDIO-BAR" data-dimension="studio" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="STUDIO-PIE" data-dimension="studio" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="STUDIO-TAG" data-dimension="studio" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET BY YEAR">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TWEET-YEAR-BAR" data-dimension="tweet_time_year" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TWEET-YEAR-PIE" data-dimension="tweet_time_year" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TWEET-YEAR-TAG" data-dimension="tweet_time_year" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET BY MONTH">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TWEET-MONTH-BAR" data-dimension="tweet_time_month" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TWEET-MONTH-PIE" data-dimension="tweet_time_month" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TWEET-MONTH-TAG" data-dimension="tweet_time_month" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET BY DAY">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TWEET-DAY-BAR" data-dimension="tweet_time_day" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TWEET-DAY-PIE" data-dimension="tweet_time_day" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TWEET-DAY-TAG" data-dimension="tweet_time_day" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET BY HOUR">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TWEET-HOUR-BAR" data-dimension="tweet_time_hour" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TWEET-HOUR-PIE" data-dimension="tweet_time_hour" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TWEET-HOUR-TAG" data-dimension="tweet_time_hour" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="TWEET BY WEEK">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="TWEET-WEEK-BAR" data-dimension="tweet_time_week" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="TWEET-WEEK-PIE" data-dimension="tweet_time_week" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="TWEET-WEEK-TAG" data-dimension="tweet_time_week" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="MOVIE BY YEAR">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="MOVIE-YEAR-BAR" data-dimension="movie_year" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="MOVIE-YEAR-PIE" data-dimension="movie_year" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="MOVIE-YEAR-TAG" data-dimension="movie_year" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="MPAA RATING">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="MOVIE-MPAA-BAR" data-dimension="mpaa_rating" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="MOVIE-MPAA-PIE" data-dimension="mpaa_rating" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="MOVIE-MPAA-TAG" data-dimension="mpaa_rating" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="RELEASE DATE BY YEAR">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="RELEASE-YEAR-BAR" data-dimension="release_date_year" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="RELEASE-YEAR-PIE" data-dimension="release_date_year" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="RELEASE-YEAR-TAG" data-dimension="release_date_year" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="RELEASE DATE BY MONTH">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="RELEASE-MONTH-BAR" data-dimension="release_date_month" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="RELEASE-MONTH-PIE" data-dimension="release_date_month" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="RELEASE-MONTH-TAG" data-dimension="release_date_month" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="RELEASE DATE BY DAY">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="RELEASE-DAY-BAR" data-dimension="release_date_day" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="RELEASE-DAY-PIE" data-dimension="release_date_day" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="RELEASE-DAY-TAG" data-dimension="release_date_day" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="RELEASE DATE BY WEEK">
                    <div data-sap-widget="switchbox" data-activeindex="1">
                        <a href="javascript:void(0)" class="iconBarChartHorizontal">Bar Chart</a>
                        <div data-sap-widget="chart" data-toplarge="25" data-title="RELEASE-WEEK-BAR" data-dimension="release_date_week" data-charttype="bar" data-color="green"></div>
                        <a href="javascript:void(0)" class="iconPieChart">Pie Chart</a>
                        <div data-sap-widget="chart" data-title="RELEASE-WEEK-PIE" data-dimension="release_date_week" data-charttype="pie" data-color="#F0AB00"></div>
                        <a href="javascript:void(0)" class="iconCorrelation">Tagcloud</a>
                        <div data-sap-widget="chart" data-topsmall="8" data-toplarge="25" data-title="RELEASE-WEEK-TAG" data-dimension="release_date_week" data-charttype="tagcloud"></div>
                    </div>
                </div>
              
                <div data-sap-widget="workareaitem" data-title="MENTION" data-source-position="6">
                <div data-sap-widget="switchbox" data-activeindex="0">
                     <!-- Optional data-sap-widget="resultlist" attributes:
                     - data-cutoverflowresults
                         ="false": resultlist shall show all results regardless the size if the resultlist container
                         ="true":  (default) show only so many results that they fit into the resultlist container
                     - data-maxresults
                         ="10": (default) number of results to be shown
                     - data-responseattributes
                         ="": (default) use default attributes of view/collection (HANA database) for ODATA response
                     - data-highlightterms
                         ="true": (default) search term is highlighted
                     -->
                     <!-- First switchbox item -->
                     <a href="javascript:void(0)" class="iconListView">Result List</a>
                     <div data-sap-widget="resultlist"
                      data-showheader="false"
                          data-maxresultslarge="8" data-maxresultssmall="3" data-responseattributes="user_screen_name,user_profile_image_url,title,movie_year,mpaa_rating,runtime,release_date,poster,studio,sent,created_at_str,tweet_source,source_url,token,sentiment,text_head,text_tail,created_at_time_str,poster_pro,synopsis"
                          data-detailwidth="650" data-detailheight="500"
                          data-highlightterms="true" data-highlightedattributes="title" data-highlightmaxlength="100" data-highlightstartposition="1"
                          data-snippetterms="false" data-snippetedattributes="title"
                          data-opendetailevent="click" data-showdetail="true"
                          data-orderby="created_at_str"
                          data-sortorder="DESC"
                          data-resulttemplate="templates/tweet.html"
                          data-resulttemplate-css="templates/tweet.css"
                          data-resulttemplate-small="templates/tweet_small.html"
                          data-resulttemplate-small-css="templates/tweet_small.css"
                          data-resulttemplate-detail="templates/tweet_detail.html"
                          data-resulttemplate-detail-css="templates/tweet_detail.css">
                     </div>
                </div>
                </div>
            </div>  <!-- end of facetrepository div -->
    </div> <!-- end of workarea div -->
    <div class="clear"></div>
    </div> <!-- end of background div -->
</body>
</html>


Create full text index

Regarding the second key point in the last section, we’ll now discuss creating full text index. First you may find the following code snippet at the beginning of the HTML body which I have not mentioned yet.


<div class="searchnfilterframe">
    <div data-useresponseattributes="false" data-usedimensions="true" data-sap-widget="searchnfilter"></div>
    </div>

So what’s that? It will display a search filter at the top of the web application. Moreover, it should be the heart & key feature of SAP HANA info access. So, I’m gonna show you in this separate section. Because we want to enable searching the used dimensions in our chart widgets instead of the used attributes in our result list, we set “data-useresponseattributes” to false and “data-usedimensions” to true. As we all know, we can use full text index to search in SAP HANA. However, SAP HANA isn’t so smart that it can create the full text index for you automatically. Currently we need to create the full text index manually. That’s why we need createFulltextIndex.js and createFulltextIndex.xsjs in our project. Since we just use createFulltextIndex.js to call createFulltextIndex.xsjs, we just need to change the URL of createFulltextIndex.js in SHINE. Here let’s just have a look at the server-side logic.

createFulltextIndex.xsjs


(function (){
    'use strict';
    //initialize variables
    var conn = null,
        body = '',
        prepStat = null;
    //initial database setup, create fulltext indizes
    try {
        //get connection
        conn = $.db.getConnection();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_TA_TOKEN_I ON "MOVIE_RATING"."$TA_TWEETS_I" ("TA_TOKEN") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_TA_TYPE_I ON "MOVIE_RATING"."$TA_TWEETS_I" ("TA_TYPE") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_SOURCE_STR_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("source_str") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_CREATED_AT_YEAR_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("created_at_year") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_CREATED_AT_MONTH_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("created_at_month") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_CREATED_AT_DAY_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("created_at_day") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_CREATED_AT_HOUR_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("created_at_hour") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX TWEET_CREATED_AT_WEEK_I ON "MOVIE_RATING"."movieRating.data::movieRating.Tweets" ("created_at_week") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_TITLE_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("title") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_MPAA_RATING_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("mpaa_rating") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_YEAR_STR_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("year_str") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_STUDIO_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("studio") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_RELEASE_DATE_YEAR_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("release_date_year") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_RELEASE_DATE_MONTH_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("release_date_month") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_RELEASE_DATE_DAY_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("release_date_day") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        prepStat = conn.prepareStatement('CREATE FULLTEXT INDEX MOVIE_RELEASE_DATE_WEEK_I ON "MOVIE_RATING"."movieRating.data::movieRating.Movies" ("release_date_week") SYNC SEARCH ONLY OFF');
        prepStat.execute();
        prepStat.close();
        // --- commit changes and close connection
        conn.commit();
        conn.close();
        body = 'fulltext index created';
        $.response.status = $.net.http.OK;
    }
    catch (e){
        // 289: index already exists, thats ok
        if(e.code && e.code !== 289){
            body = e.message;
            $.response.status = $.net.http.BAD_REQUEST;
        } else {
            body = 'fulltext index already exists';
            $.response.status = $.net.http.OK;
        }
    }
    $.response.contentType = 'text/plain';
    $.response.setBody(body);
}());









You can see in the above XSJS file, we create 16 full text indexes for the dimensions in our chart widgets except SENTIMENT BY MOVIE if these full text indexes do not exist. Otherwise, we need to handle the exception. Now you may ask, “Can I run these SQL statements in SQL console manually?” Absolutely you can. But considering the DU transportation, it’s better to use this dynamic way.

Besides we can also set the “Search Properties” in our AT_TWEETS.attributeview. For more details, please refer Modeling Your Search Content – SAP HANA Developer Guide – SAP Library

24.PNG

Look & feel

Now it’s time to show the look & feel! You can find four parts from the following window dump.

  • Search filter in red box
  • Facet pane in green box with six default chart widgets
  • Content pane in blue box with result list
  • Facet repository in yellow box with 17 chart widgets, you can drag and drop them to facet pane.

As you can see, since we filter the movie title to “The Judge”, everything including the chart widgets and the result list will only display the stuff with this movie.

/wp-content/uploads/2014/11/25_1_578349.png

Now let’s click one mention and the following overlay container will prompt to us. It’ll show you the very detailed tweet info and mentioned movie info. From strong positive sentiment to strong negative sentiment, we use green to red, similar with the traffic light. In addition, the sentiment token is also highlighted in the tweet text. Remember in Real-time sentiment rating of movies on SAP HANA (part 2) – data preparation, we insert tweets into SAP HANA in real-time and the movie sentiment is continuously analyzed by SAP HANA. So with this smart app, we can analyze the movie sentiment in real-time! For instance, you can analyze the sentiment and # of mentions of a specific movie or you can even analyze all new release movies in current week. Exciting? 😆

26.PNG

Movie Sentiment Rating based on SINA

Still not enough? Don’t worry. I’ve recorded a video for you. In the following video I’ll show you how to use this smart app to analyze the movie sentiment based on SINA.

Next steps

In this blog, we’ve jumped into SAP HANA info access and built our first movie smart app based on it. With the simplicity of SAP HANA info access, we are able to finish our first app in a very short time. What we need is just an attribute view and some front-end stuff like HTML, CSS and JavaScript. We did less but got more. In the next blog, we will have a look at sap.m (a package in SAPUI5) and build our movie app on mobile devices. See you soon.

Hope you enjoyed reading my blog and playing with the smart app. 🙂

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. John Leggio

    Hi Wenjun, where can I find the HANA Content: Information Access tgz file?

    Can you provide the direct download path?

    HCO_INA_SERVICE.tgz

    HCOINAUITOOLKIT.tgz

    (0) 

Leave a Reply