---
title: "LINQを使ったSearchインデックスをSitecoreに変換"
slug: "search-indexes-using-linq-to-sitecore"
abstract: "LINQからSitecoreへの接続は、標準的なLINQクエリを使ってインデックスを検索するアクセスを提供します。"
---
# LINQを使ったSearchインデックスをSitecoreに変換

LINQ to Sitecoreは、LINQ to SQLやLINQ to Objectsなど他のLINQプロバイダーと同様に、標準的なLINQクエリを使ってインデックスを検索できます。標準IQueryable<T> インターフェースを使用し、ほとんどの利用可能な操作をサポートしています。LINQの一般的な紹介については、[http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx](http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx)を参照してください。

LINQ層は、一般的なクエリを検索提供者が理解できるものに変換する抽象層です。

例えば、LINQレイヤーは次のようなクエリを解決します:

var query = context.GetQueryable<Product>.Where(item => item.Name == “Sample Item”)

検索プロバイダーが理解できるものに変換します。新しい検索プロバイダーを導入すれば、そのプロバイダーもクエリを理解できます。

LINQレイヤーはSitecore内部で使われていますが、開発者も利用できます。このレイヤーはサブレイアウトで使うことができます。

検索を開始するには、検索コンテキストを設定します:

using (var context = ContentSearchManager.GetIndex(item).CreateSearchContext())
{
 IQueryable<SearchResultItem> searchQuery = context.GetQueryable<SearchResultItem>().Where(item => item.Name == “Sitecore”)
}

LINQレイヤーはクエリをプロバイダーが理解できるものに変換します。

これは検索インデックス上でのクエリ結果を返し、SearchResultItem型として返します。また、インデクサーを使ってクエリを実行することもできます:

using (var context = ContentSearchManager.GetIndex(item).CreateSearchContext())
{
 IQueryable<SearchResultItem> searchQuery = context.GetQueryable<SearchResultItem>().Where(item => item“\_name” == “Sitecore”)
}

このトピックでは以下の内容を説明します:

-   [サポートされているIQueryableメソッド](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/search-indexes-using-linq-to-sitecore.html#UUID-be814066-efb5-a17f-e041-25ac69385d6a_id__Supported_IQueryable_methods "Supported IQueryable methods")
-   [LINQからSitecoreへの構文](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/search-indexes-using-linq-to-sitecore.html#UUID-be814066-efb5-a17f-e041-25ac69385d6a_id__LINQ_to_Sitecore "LINQ to Sitecore syntax")
-   [IQueryable extensions](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/search-indexes-using-linq-to-sitecore.html#UUID-be814066-efb5-a17f-e041-25ac69385d6a_id__IQueryable_extensions "IQueryable extensions")
-   [カスタム検索タイプ/オブジェクトマッピング](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/search-indexes-using-linq-to-sitecore.html#UUID-be814066-efb5-a17f-e041-25ac69385d6a_id__Custom_search_typeobject "Custom search type/object mapping")
-   [カスタムテキスト翻訳機](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/search-indexes-using-linq-to-sitecore.html#UUID-be814066-efb5-a17f-e041-25ac69385d6a_section-idm4482770353900832996770524005 "Custom text translators")

## サポートされているIQueryableメソッド

LINQレイヤーはすべてのIQueryableメソッドを実装しているわけではありません。

以下の方法がサポートされています:

-   標準文字列、整数、float、または実装された任意の型でソートしてください IComparable
-   全員
-   そして
-   どんな人でも
-   間に
-   ブースト
-   キャスト
-   定数
-   包含
-   伯爵
-   エレメントアット
-   終わり
-   同等
-   ファセトン
-   FacetPivotOn
-   フィールド
-   フィルター
-   まず
-   GetFacets
-   結果を取る
-   グレータータン
-   グレーター・ザン・ザ・オア・イコール
-   GroupJoin(グループジョイン)
-   インコンテキスト
-   参加
-   ラスト
-   レスタン
-   レスタンオレイコール
-   例えば
-   マッチオール
-   試合
-   マッチノン
-   ミン
-   マックス
-   否定
-   そうじゃない
-   ノット・イコール
-   あるいは
-   OrderBy
-   距離順
-   セレクト
-   セレクトマニー
-   シングル
-   スキップ
-   StartsWith
-   例えば
-   連合
-   ここで
-   ワイルドカードマッチ
-   WithinRadius
-   ToList()
-   ToLookUp()
-   ToDictionary()
-   StartsWith

### サポートされていないIQueryableメソッド

以下の方法はサポートされていません:

-   平均
-   コンキャット
-   ファセット
-   ファースト・オア・デフォルト
-   グループ・ビー
-   交差点
-   LastorDefault
-   試合
-   降順順
-   裏面
-   シングル・オア・デフォルト
-   スキップ・ホット
-   サム
-   テイクホウッド

これらのメソッドが呼び出されると、実行時にNotSupportedExceptionまたはInvalidOperationException例外がスローされます。

## LINQからSitecoreへの構文

この表はLINQ層とSolrの対応を示しています:

**Solr 構文**

**LINQからSitecoreへ**

**フィールド**

\_text:”go”

.Where(c => c.Text == "go")  
  
\- または:  
  
.Where(c => c.Text.Equals(“go”))

**ワイルドカード**

\_text:\*amber\*

.Where(c => c.Text.Contains ("amber"))

**接頭辞**

\_text: amber\*

.Where(c => c.ContactName.StartsWith("amber"))

**ファジー**

\_text:roam~  
  
\_text:roam~0.8

.Where(c => c.Text.Like("roam"))  
  
.Where(c => c.Text.Like("roam", 0.8))

**近接性**

\_text:"jakarta apache"~10

.Where(c => c.Text.Like("jakarta apache", 10))

**包括的範囲**

\_\_smallupdateddate:20140101 TO 20150101

.Where(c => c.Updated.Between(new DateTime(2014, 1, 1), new DateTime(2015, 1, 1), Inclusion.Both)

**エクスクルーシブ・レンジ**

\_title:{Aida TO Carmen}

.Where(c => c.Title.Between("Aida", "Carmen", Inclusion.None))

**ブースト**

\_name:jakarta^4 apache

.Where(c => c.Name.Equals("jakarta").Boost(4) || c.Name.Equals("apache"))

**ブールまたは**

\_name:"jakarta apache" OR \_name:jakarta

.Where c.Name.Equals("jakarta apache") || c.Name.Equals("jakarta")

**ブール量と**

\_name:"jakarta apache" AND \_text:"go"

.Where c.Name.Equals("jakarta apache") && c.Text.Equals("go")

**ブール値ではありません**

\_name:"jakarta apache" NOT \_name:"Apache Solr"

.Where c.Name.Equals("jakarta apache") && !c.Name.Equals("Apache Solr")

**グルーピング**

\_name:(jakarta OR apache) AND \_text:go

where (c.Name == "jakarta" || c.Name == "apache") && (c.Text == "go")

## IQueryable extensions

LINQレイヤーは標準IQueryableインターフェースを拡張する追加メソッドを提供します。使用するにはSitecore.ContentSearch.Linq名前空間を宣言する必要があります。

### フィルタリング

フィルタリングは、Whereを使って結果リストを制限するのと似ています。 Filterを使うと、検索ヒットのスコアリングやランキングはフィルターの影響を受けず、検索パフォーマンスを最適化するためにフィルターをキャッシュできます。

例えば:

results = queryable.Filter(d => d.Id > 4 && d.Id < 8);

> !注検索結果のランキングに影響を与えないため、GetGlobalFiltersパイプライン内の検索クエリに制限を適用する際にFilterを使用してください。

### ファセット

#### 単純なファセット加工

var results = queryable.FacetOn(d => d.Name);
var facets = results.GetFacets();
foreach (var category in facets.Categories) {
 Console.WriteLine(category.Name);
 foreach (var facetValue in category.Values) {
 Console.WriteLine("{0}: {1}", facetValue.Name, facetValue.Aggregate);
 }
}

#### ピボットファセティング

var results = queryable.FacetPivotOn(p => p.FacetOn(d => d.Name).FacetOn(d => d.Year));
var facets = results.GetFacets();
foreach (var category in facets.Categories) {
 Console.WriteLine(category.Name);
 foreach (var facetValue in category.Values) {
 Console.WriteLine("{0}: {1}", facetValue.Name, facetValue.Aggregate);
 }
}

#### ブースト

queryable.Where(it => (it.TemplateName == "Sample Item").Boost(50) || it.TemplateName=="Folder");
queryable.Where(it => (it.Paths.Contains(new ID("{0DE95AE4-41AB-4D01-9EB0-67441B7C2450}")).Boost(3) || it.TemplateName=="Folder") );

### その他

#### 間に

results = queryable.Where(item => item.Price.Between(50.0f, 400.0f, Inclusion.Both));
results = queryable.Where(item => item.Price.Between(2.0f, 12.0f, Inclusion.Both) || item.Price.Between(80.0f, 400.0f, Inclusion.Both));
results = queryable.Where(d => d.Date.Between(new DateTime(2004, 12, 31), DateTime.Now, Inclusion.Both));
results = queryable.Where(d => d.Id.Between(1, 4, Inclusion.Both));
results = queryable.Where(d => d.Id.Between(1, 4, Inclusion.Lower));
results = queryable.Where(d => d.Id.Between(1, 4, Inclusion.Upper));
results = queryable.Where(d => d.Id.Between(1, 4, Inclusion.None));

#### 文字列。含まれます

results = queryable.Where(d => !d.Template.Contains("Hello:));

#### ストリング。比較

results = queryable.Where(d => !d.Name.CompareTo("Hello") == 1);

#### 同等

results = queryable.Where(d => d.Id.Equal(4));

#### 試合

results = queryable.Where(i => i.Template.Matches("^.\*$"));

#### マッチワイルドカード

results = queryable.Where(i => i.Template.Where(i => i.Template.MatchWildcard("H?li\*m")));

#### 例えば

results = queryable.Where(i => i.Template.Like("Citecoar"));

#### ストリング。始まる

results = queryable.Where(d => !d.Name.StartsWith("Hello"));

#### 糸。終わり

results = queryable.Where(d => !d.Name.EndsWith("Hello"));

#### 結果を取る

results = queryable.GetResults().Hits.Where(i => i.Document.Name.Contains("o")).Where(hit => hit.Score > 0.6);

#### GetFacets

results = queryable.Where(d => d.Id > 0).FacetOn(d => d.Template, 0).GetFacets();

## カスタム検索タイプ/オブジェクトマッピング

LINQレイヤーは検索インデックスを公開するために汎用IQueryable<T> インターフェースを使用しているため、インデックス内の情報を記述するためにカスタムクラスやPOCOクラスを使うことができます。

カスタムサーチ型を実装するには、そのようなクラスは以下を条件とします:

-   空のコンストラクターを用意してください。
-   ゲッターやセッター、または検索結果データを保持するパブリックインデクサーで公開プロパティを公開します。

LINQプロバイダーは、インデックス内のドキュメントフィールドをカスタム検索タイプのプロパティにプロパティ名で自動的にマッピングします。名前でマッチングされていないインデックスのプロパティやフィールドは、オブジェクト作成やマッピング時にスキップされます。

また、IndexField属性でプロパティを装飾することで、インデックス内のフィールドに一致しないプロパティをマッピングすることも可能です。例えば、\_nameのような特別なSitecoreフィールドを「 Name」というプロパティとして公開するために使うことができます。別の用途としては、フィールド名にスペースがある場合があり、名前だけで直接プロパティにマッピングすることはできません。

さらに、フィールド名をキーとして、各フィールドの値をインデックスドキュメントに入力するインデクサを実装することもできます。また、インデクサーを異なる型としてラップするためのObjectIndexerKeyもあります。これは、プロパティ名の文字列版しか持っていなくても、プロパティ型のインデクサーとして使う必要がある場合、最も多い場合はintが必要です。

カスタム型を提供し、Sitecoreがインデックスフィールドからアイテムのプロパティにマッピングするプロセスも「ハイドレーション」とも呼ばれます。

### 対応型

インデックス文書フィールドをプロパティにマッピングする際の自動タイプ変換には、以下のタイプがサポートされています:

-   .NET 組み込み積分型
-   .NET 組み込みの浮動小数点型
-   ブール
-   ストリング
-   デートタイム
-   ガイド
-   Sitecore ID
-   Sitecore ShortID
-   Sitecore ItemUri
-   IEnumerable
-   DateTimeOffset(日付時間オフセット)
-   言語
-   バージョン
-   データベース
-   カルチャーインフォ
-   タイムスパン

### カスタム検索タイプの例

以下はカスタム検索タイプの実装例です:

public class MySearchResultItem
{
 // Fields
 private readonly Dictionary<string, stringfields = new Dictionary<string, string>();
 // Properties
 // Will match the \_name field in the index
 IndexField("\_name")
 public string Name { get; set; }
 // Will match the myid field in the index
 public Guid MyId { get; set; }
 public int MyNumber { get; set; }
 public float MyFloatingPointNumber { get; set; }
 public double MyOtherFloatingPointNumber { get; set;}
 public DateTime MyDate { get; set; }
 public ShortID MyShortID { get; set; }
 public ID SitecoreID { get; set; }
 // Will be set with key and value for each field in the index document
 public string thisstring key
 {
 get
 {
 return this.fieldskey.ToLowerInvariant();
 }
 set
 {
 this.fieldskey.ToLowerInvariant() = value;
 }
 }
}

### ハイライト

Solrには、クエリ応答にクエリに一致する文書の断片を含めることができるハイライト機能があります。

Solrを使って検索結果をハイライトするには、[カスタム検索タイプにハイライトを追加](https://doc.sitecore.com/xp/en/developers/104/platform-administration-and-architecture/add-highlighting-to-a-custom-search-type.html) し、[その検索タイプ内でハイライトを設定する](https://doc.sitecore.com/xp/en/developers/104/platform-administration-and-architecture/configure-highlighting-in-a-custom-search-type.html)ことができます。

## カスタムテキスト翻訳機

カスタムテキスト翻訳ツールを作成して、LINQクエリをネイティブ検索クエリに変換する方法を制御できます。

これにより、ネイティブ検索クエリを検索動作や言語ルールの要件に合わせてカスタマイズできます。

登録済みのテキスト翻訳機はSolrインデックスの設定ファイル(デフォルトでSitecore.ContentSearch.Solr.DefaultIndexConfiguration.config )で見つけることができます。

> !警告デフォルトのテキスト翻訳機の変更は控えてください。

### カスタムテキスト翻訳機の作成

カスタムテキスト翻訳ツールはLINQクエリのテキストを変換し、その結果得られるネイティブ検索クエリを生成します。

以下はカスタムテキスト翻訳ツールの作成と使用方法の例です:

1.  Sitecore.ContentSearch.Linq.Parsing.BaseTextQueryTranslator<AbstractSolrQuery>から派生したクラスを作成します。
    
    using Sitecore.ContentSearch.Linq.Parsing;
    using Sitecore.ContentSearch.SolrNetExtension.Queries;
    using SolrNet;
    
    namespace Custom
    {
     public class HelloWorldSolrTextQueryTranslator : BaseTextQueryTranslator<AbstractSolrQuery>
     {
     public override AbstractSolrQuery Translate(string query, TextQueryTranslatorContext context)
     {
     return new ExactMatchQueryByField(context.FieldName, query, true) && new ExactMatchQueryByField(context.FieldName, "Hello World!", true);
     }
     }
    }
    
2.  クラスでアセンブリをコンパイルして有効化します。
    
3.  インデックス設定でカスタムテキスト翻訳機を登録します:
    
    <?xml version="1.0" encoding="utf-8" ?>
     <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
     <sitecore role:require="Standalone or ContentManagement or ContentDelivery" search:require="solr">
     <contentSearch>
     <indexConfigurations>
     <defaultSolrIndexConfiguration>
     <searchOptions>
     <textQueryTranslatorStore>
     <queryTranslators>
     <queryTranslator key="custom" type="Custom.HelloWorldSolrTextQueryTranslator, Custom" />
     </queryTranslators>
     </textQueryTranslatorStore>
     </searchOptions>
     </defaultSolrIndexConfiguration>
     </indexConfigurations>
     </contentSearch>
     </sitecore>
     </configuration>
    
    カスタムテキスト翻訳ツールはLINQクエリで使うことができます。例えば:
    
    var results = context.GetQueryable<SearchResultItem>()
     .Where(item => item.Content.Search("(6+2):2=4", TextTranslator.FromName("custom")))
     .GetResults();
    
    前のLINQクエリを実行すると、Searchログに以下の翻訳済みSolrクエリが表示されます: q=(\_content:("(6+2):2=4") AND \_content:("Hello World!")) AND \_val\_:\_\_boost。