Developer Guide
ご覧のページは、お客様の利便性のために一部機械翻訳されています。また、ドキュメントは頻繁に更新が加えられており、翻訳は未完成の部分が含まれることをご了承ください。最新情報は都度公開されておりますため、必ず英語版をご参照ください。翻訳に問題がある場合は、 こちら までご連絡ください。

検索クエリとフィルター

検索エンジンから適切な結果を得るには、適切なクエリを提供する必要があります。 Liferay のクエリ API は portal-search-api モジュールにあり、クエリとフィルターの両方を構築するために使用されます。

フィルター はすべての検索ドキュメントに対して「はい」または「いいえ」の質問をし、関連性を計算しません。 フィルターは、 ステータス フィールドはステージングとライブのどちらに等しいか?を尋ねる場合があります。

クエリ は同じ「はい」または「いいえ」の質問をして、ドキュメントが指定された基準にどの程度一致しているかを計算します。 これは 関連性スコアリングの概念です。 クエリは次のように尋ねます ドキュメントのコンテンツ フィールドに「Liferay」、「コンテンツ」、または「管理」という単語が含まれていますか? また、ドキュメントのコンテンツは検索されたキーワードとどの程度関連していますか?

Liferay でクエリとフィルターを使用するには、クエリを作成し、それをクエリまたはフィルターとしてリクエストに追加します。

  1. SearchRequestBuilder.query(fooQuery)を使用して、リクエストにクエリを追加します。

  2. クエリではなくフィルタリングするには、 SearchRequestBuilder.postFilterQuery(fooQuery)を使用して検索リクエストに追加します。

ここでは、 会社インデックスを照会する Gogo Shell コマンド をデプロイ、テスト、検査できます。

ヒント

開発中に、検索エンジンによって生成されたクエリを検査すると役立ちます。 詳細については、 Liferay が生成した Elasticsearch クエリの検査 を参照してください。

カスタム検索クエリを使用した Gogo Shell コマンドのデプロイ

新しいLiferay インスタンスを起動し、以下を実行します。

docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.132-ga132

http://localhost:8080でLiferayにサインインします。 メールアドレス test@liferay.com とパスワード testを使用してください。 プロンプトが表示されたら、パスワードを learnに変更します。

次に、プロジェクトをダウンロードし、いくつかの前提条件を満たします。

  1. liferay-b9f3 プロジェクトをダウンロードして解凍します。

    curl https://resources.learn.liferay.com/examples/liferay-b9f3.zip -O
    
    unzip liferay-b9f3.zip
    
  2. モジュールのルートから、ビルドおよびデプロイします。

    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    

    このコマンドは、デプロイされたjarをDockerコンテナ上の /opt/liferay/osgi/modules にコピーするのと同じです。

  3. Liferay Dockerコンテナコンソールでデプロイを確認します。

    STARTED com.acme.b9f3.impl_1.0.0 [1775]
    
  4. B9F3 サンプルには、ドキュメントとコンテンツを Liferay にロードするシェル スクリプトが含まれています。 これを実行するには、まず実行中の Liferay インスタンスからデフォルトのサイトの ID とグローバル サイトの ID を取得します。

    デフォルトサイトで、 サイト メニュー (Site Menu) → 構成サイト設定を開きます。

  5. サイト構成 に移動して、サイト ID を記録します。

  6. グローバルサイトへアクセスしてください。 サイトセレクター (Site Selector) → 利用可能なサイトグローバルをクリックします。

  7. グローバル サイトのサイト ID を見つけて記録します。

  8. スクリプトを実行するには、ターミナルで liferay-b9f3/curl に移動します。

  9. サイト ID を引数としてシェル スクリプトを実行します。

    ./populate_b9f3.sh [default site ID] [global site ID]
    

    例えば、

    ./populate_b9f3.sh 20116 20119
    

    スクリプトは次のリソースを追加します。

    • Webコンテンツ:

      • エイブルコンテンツ
      • エイブルコンテンツフォルダ
        • エイブルコンテンツ
    • ドキュメントとメディア:

      • エイブルドキュメント
      • エイブルドキュメントフォルダー
        • エイブルドキュメント

B9F3検索クエリをテストする

  1. ローカルで実行されている Liferay のホームページで、検索バーに「 able 」と入力します。 6 件の結果が表示されます。

  2. グローバル メニュー (Global Menu) を開き、 コントロール パネルGogo Shellに移動します。

  3. b9f3:searchable と入力し、CAPTCHA チャレンジに答えてください。

  4. 実行をクリックします。

    Gogo シェルから検索クエリを実行できます。

  5. 4 つの結果が表示されますが、すべてルート コンテンツです。 作成されたフォルダー内にネストされているものには、 folderId0ではないため、返されません。 ただし、フォルダー自体はルート フォルダーに含まれており、 folderId0と指定されているため、返されます。

ヒント

ドキュメントおよびメディアおよび Web コンテンツ アプリケーションのルート フォルダーには、 folderId0あります。 検索結果ウィジェットで 結果をドキュメント形式で表示 を有効にすると、各検索結果のインデックス付きフォルダー ID を確認できます。 詳細については、「 検索エンジンドキュメントの検査 」を参照してください。

B9F3検索クエリを理解する

まず、 SearchRequestBuilderを初期化します。 このオブジェクトを使用して検索要求を構築できます。

SearchRequestBuilder searchRequestBuilder =
	_searchRequestBuilderFactory.builder();

次に、リクエスト内に SearchContext を入力します。 これにより、検索するエントリ クラス名と、検索するインスタンスの会社 ID が設定されます。 検索するキーワードも設定します。 これらのキーワードは、検索時にユーザーによって入力されます。

検索コンテキストにキーワードを設定するか、 searchRequestBuilder.emptySearchEnabled(true);を使用してリクエスト ビルダーで空の検索を有効にする必要があります。

searchRequestBuilder.withSearchContext(
	searchContext -> {
		searchContext.setCompanyId(_portal.getDefaultCompanyId());
		searchContext.setEntryClassNames(
			new String[] {
				"com.liferay.document.library.kernel.model.DLFileEntry",
				"com.liferay.document.library.kernel.model.DLFolder",
				"com.liferay.journal.model.JournalArticle",
				"com.liferay.journal.model.JournalFolder"
			});
		searchContext.setKeywords(keywords);
	});

次にクエリ句を作成します。 この例では、ブールクエリ内に 2 つの MUST クエリ句がネストされています。1 つの句は、 folderId フィールドを値 0に一致させるための用語クエリであり、もう 1 つは、ユーザーの検索キーワードとローカライズされたタイトル フィールドの完全なテキスト一致クエリを実行するためのものです。

BooleanQuery booleanQuery = _queries.booleanQuery();

booleanQuery.addMustQueryClauses(
	_queries.term(Field.FOLDER_ID, "0"),
	_queries.match(
		StringBundler.concat(
			"localized_", Field.TITLE, StringPool.UNDERLINE,
			LocaleUtil.US),
		keywords));

ネストされた句を含むブールクエリをリクエストに追加し、リクエストを実行して、必要に応じて応答を処理します。 これはドキュメントの uid フィールドとそのスコアを出力します。

SearchRequest searchRequest = searchRequestBuilder.query(
	booleanQuery
).build();

SearchResponse searchResponse = _searcher.search(searchRequest);

SearchHits searchHits = searchResponse.getSearchHits();

for (SearchHit searchHit : searchHits.getSearchHits()) {
	Document document = searchHit.getDocument();

	String uid = document.getString(Field.UID);

	System.out.println(
		StringBundler.concat(
			"Document ", uid, " has a score of ",
			searchHit.getScore()));
}

これらの Liferay サービスは、B9F3 コードで参照されています。

@Reference
private Portal _portal;

@Reference
private Queries _queries;

@Reference
private RoleLocalService _roleLocalService;

@Reference
private Searcher _searcher;

@Reference
private SearchRequestBuilderFactory _searchRequestBuilderFactory;

@Reference
private UserLocalService _userLocalService;

ネストされたクエリの実装

オブジェクト フィールド、Web コンテンツ構造フィールド、またはドキュメント メタデータ セットのクエリを作成するには、 ネストされたクエリを使用して、ネストされた構造に従ってフィールドをクエリする必要があります。 クエリ内でパスを指定し (例: Web コンテンツおよびドキュメント メタデータ セットの場合は ddmFieldArray 、オブジェクトの場合は nestedFieldArray )、ドット表記を使用する 2 つの句を含むブール クエリを作成します。1 つの句はフィールド名と一致し、もう 1 つの句は値 (ユーザーのキーワードなど) と一致します。

Webコンテンツ構造フィールドのクエリ

Web コンテンツの構造、ドキュメント、メディア メタデータ セットも同様にインデックス付けされます。 Web コンテンツ構造フィールドは次のようにインデックス付けされます。

{
   ddmFieldName=ddm__text__35174__Text25689566_en_US,
   ddmFieldValueText_en_US_String_sortable=able text,
   ddmValueFieldName=ddmFieldValueText_en_US,
   ddmFieldValueText_en_US=Able text
}

Elasticsearch のクエリ構文では、フィールドに対して次のようなクエリを作成できます。

{
  "nested": {
    "path": "ddmFieldArray",
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "ddmFieldArray.ddmFieldName": "ddm__text__35174__Text25689566_en_US"
            }
          },
          {
            "match": {
              "ddmFieldArray.ddmFieldValueText_en_US": "${keywords}"
            }
          }
        ]
      }
    }
  }
}

Liferay の Java 検索 API でも同じクエリを作成できます。

BooleanQuery booleanQuery = queries.booleanQuery();

MatchQuery fieldNameQuery = queries.match("ddmFieldArray.ddmFieldName", "ddm__text__35174__Text25689566_en_US");

MatchQuery fieldValueQuery = queries.match("ddmFieldArray.ddmFieldValueKeyword_en_US", keywords);

booleanQuery.addMustQueryClauses(fieldNameQuery, fieldValueQuery);

NestedQuery nestedQuery = queries.nested("ddmFieldArray", booleanQuery);

オブジェクトフィールドのクエリ

オブジェクトのテキスト フィールドは次のようにインデックス付けされます。

[
   {
      fieldName=fooText,
      value_en_US=Able Text,
      valueFieldName=value_en_US
   },
   {
      fieldName=fooText,
      value_keyword_lowercase=Able Text,
      valueFieldName=value_keyword_lowercase
   }
]

Elasticsearch のクエリ構文では、フィールドに対して次のようなクエリを作成できます。

{
  "nested": {
    "path": "nestedFieldArray",
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "nestedFieldArray.fieldName": "fooText"
            }
          },
          {
            "match": {
              "nestedFieldArray.value_en_US": "${keywords}"
            }
          }
        ]
      }
    }
  }
}

Liferay の Java 検索 API でも同じクエリを作成できます。

BooleanQuery booleanQuery = queries.booleanQuery();

MatchQuery fieldNameQuery = queries.match("nestedFieldArray.fieldName", "fooText");

MatchQuery fieldValueQuery = queries.match("nestedFieldArray.value_en_US", keywords);

booleanQuery.addMustQueryClauses(fieldNameQuery, fieldValueQuery);

NestedQuery nestedQuery = queries.nested("nestedFieldArray", booleanQuery);

フィルタリング

フィルタリング用の個別の API はありません。 通常どおりクエリを構築し、検索リクエストに追加して、 SearchRequestBuilder.postFilterQuery(fooQuery) メソッドを使用してフィルターとして指定します。

たとえば、B9F3 コードを変更して、最初に folderId0 であるドキュメントをフィルターし、次にキーワードとタイトル フィールドに対して一致クエリを実行できます。

TermQuery termQuery = _queries.term(Field.FOLDER_ID, "0");

searchRequestBuiler.postFilterQuery(termQuery);

MatchQuery matchQuery = _queries.match(
    StringBundler.concat(
        "localized_", Field.TITLE, StringPool.UNDERLINE,
           LocaleUtil.US), keywords);

searchRequestBuilder.query(matchQuery);

SearchRequest searchRequest = searchRequestBuilder.build();