Skip to content
This repository was archived by the owner on Oct 5, 2020. It is now read-only.

Quick Customization Recipes

Patrick McElwee edited this page Feb 6, 2017 · 1 revision

Customization Recipes

Recipes on this page:

To add a facet to the default search page, you will need to create a range index and a search constraint. Once you do that, the out-of-the-box application will display a facet for that constraint on the search page. (This is done using the ml-facets directive that is part of the ml-search-ng library.)

Step One to add a facet: Create a range index

Range indexes are added to deploy/ml-config.xml. There are comments there with examples of several kinds of range indexes. You should be able to uncomment one

For example, to add a range element index on <name>, add this inside <database> and <range-element-indexes> elements:

<range-element-index>
  <scalar-type>string</scalar-type>
  <namespace-uri/>
  <localname>name</localname>
  <collation>http://marklogic.com/collation/codepoint</collation>
  <range-value-positions>false</range-value-positions>
</range-element-index>

Then run this to add the index to the server:

./ml local bootstrap

Step Two to add a facet: Create a search constraint

When searching in MarkLogic, query options can be saved on the server and invoked during the search. Constraints are one type of option.

The out-of-the-box options file is found in rest-api/config/options/all.xml. (Note that, as you expand your app, you can add other search options configurations and use them in certain searches.)

To add the search constraint we need, add this inside the <search:options> element:

<constraint name="Name">
  <range type="xs:string" facet="true" collation="http://marklogic.com/collation/codepoint">
    <facet-option>limit=5</facet-option>
    <facet-option>frequency-order</facet-option>
    <facet-option>descending</facet-option>
    <element ns="" name="name"/>
  </range>
</constraint>

Then run this to deploy those updated options to the MarkLogic server:

./ml local deploy rest

If the index and option are configured correctly, and are populated with some data, you should see the 'Name' facet on the search page.

Customize Search Results

For this example, create a few documents using the Create page in the app. After creating a few documents, the search page should look something like this:

Instead of showing the uri for the file, let's use the name of the person in each document. Also, let's always show the company that the person works for in the search results.

There are two changes we have to make in order for this to work:

  1. change the search options to always return the name and company data for each search result
  2. change the search results HTML to display the name and company data

To add the name and company data to the search results coming back from the search query from the MarkLogic search call to the REST API, add an extract-document-data config element to rest-api/config/options/all.xml:

...
<extract-document-data selected="include">
    <extract-path>/name</extract-path>
    <extract-path>/company</extract-path>
  </extract-document-data>

</options>

Since this is a change to the search options xml we have to deploy it to the server. Do that by executing ./ml local deploy modules.

Next, we change the HTML ui/app/search/search-results.html. The data we specified in extract-document-data will be in result.extracted.content. Note that each extract-path in extract-document-data will appear as a separate array item in result.extracted.content. So the name value will be result.extracted.content[0].name (note that 0 index) and the company value will be result.extracted.content[1].company (note that 1 index).

Change to ui/app/search/search-results.html be:

<div ng-repeat="result in results">
  <h4>
    <a ui-sref="root.view({uri: result.uri})">{{ result.extracted.content[0].name }}</a>
  </h4>
  <div>Company: {{ result.extracted.content[1].company }}</div>
  <div class="matches">
    <div class="match" ng-repeat="match in result.matches">
      <em ng-repeat="text in match['match-text'] track by $index">
        <span ng-class="{ highlight: !!text.highlight }">{{ text.highlight || text }}</span>
      </em>
    </div>
  </div>
  <hr/>
</div>

If you are already running your server using gulp serve-local the change should be detected and your browser should automatically refresh. If not, run gulp build and then refresh the browser.

Your screen should now look something like this:

Change the collection used in search

Sometimes you may load data into your database using a different collection than data which is what the slush application uses by default. When you go to search you'll see no results even though the data is in your database.

The collection to search against is in rest-api/config/options/all.xml in the additional-query section:

...
<additional-query>
    <cts:collection-query xmlns:cts="http://marklogic.com/cts">
      <cts:uri>data</cts:uri>
    </cts:collection-query>
  </additional-query>
...

In this example, I created a few json files for sample data in the data directory that look like this (bob_jones.json):

{
  "name": "Bob Jones",
  "eyeColor": "blue"
}

I loaded the documents into my database and put them in the people collection using this mlcp command:

mlcp import -host localhost -port 8377 -username admin -password admin -input_file_path data -input_file_pattern '.*\.json' -output_collections people

I changed rest-api/config/options/all.xml to search the people collection:

...
<additional-query>
    <cts:collection-query xmlns:cts="http://marklogic.com/cts">
      <cts:uri>people</cts:uri>
    </cts:collection-query>
  </additional-query>
...

Deploy the changed file using ./ml local deploy modules and then the results look like this:

Use a Show More feature in facets

The number of facet values that are shown is controlled by a facet-option in the search options xml. For the eyeColor facet, the limit is 5. For this example, let's change it to 3 (rest-api/config/options/all.xml):

...
<constraint name="eyeColor">
    <range type="xs:string" facet="true" collation="http://marklogic.com/collation/codepoint">
      <facet-option>limit=3</facet-option>
      <facet-option>frequency-order</facet-option>
      <facet-option>descending</facet-option>
      <json-property>eyeColor</json-property>
    </range>
  </constraint>
...

Deploy the changes using ./ml local deploy modules.

The search page should look like this (make sure you've got at least 7 or 8 eyeColor values in your documents to be able to notice the changes in the facets):

Now let's add a Show More functionality to the facet. In ui/app/search/search.html add show-more="ctrl.showMoreFacets(facet, facetName, 5)" to the ml-facets element. The "5" is how many more facet values you want to load after clicking See More. Your HTML should look like this:

...
<ml-facets class="col-md-3 right-col" facets="ctrl.response.facets" toggle="ctrl.toggleFacet(facet, value)" 
active-facets="ctrl.mlSearch.activeFacets" negate="ctrl.toggleNegatedFacet(facet,value)" 
show-more="ctrl.showMoreFacets(facet, facetName, 5)"></ml-facets>
...

Now it should look like this:

Click See More to see more facets values.

Clone this wiki locally