3

1つのクエリ「tags」と「items」で2つのコレクションを返したいのですが、各タグには0..manyアイテムを含めることができます。プロジェクションを使用すると、2つのコレクションではなく、2つの列を持つ単一のコレクションを想定しているように見えますが、それは正しいですか?この検索クエリを実行するためのより良い方法はありますか?

私は得ています"the query response contains columns Tags, Items however ...anonymous type does not contain settable properties to receive this data"

var query =  client
    .Cypher
    .StartWithNodeIndexLookup("tags", "tags_fulltext", keyword)
    .Match("tags<-[:TaggedWith]-items")
    .Return((items, tags) => new 
    {
        Tags = tags.As<Tag>(),
        Items = items.As<Item>()
    });

var results = await query.ResultsAsync;

return new SearchResult
{
    Items = results.Select(x => x.Items).ToList(),
    Tags = results.Select(x => x.Tags).Distinct().ToList()
};
4

1 に答える 1

4

オプション1

シナリオ:キーワードに一致するすべてのタグを取得してから、それらのタグごとに、各アイテムを取得します(タグにリンクする方法で)。

まず、この行:

.StartWithNodeIndexLookup("tags", "tags_fulltext", keyword)

する必要があります:

.StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)

つまり、アイデンティティはであってはなりtagませんtags。これは、句の結果が、と呼ばれるノードのセットではなく、STARTそれぞれがaであるノードのセットになるためです。セマンティクスですが、次のステップで物事が簡単になります。tagtags

tagの代わりに呼び出しているので、句を次のようtagsに更新します。MATCH

.Match("tag<-[:TaggedWith]-item")

つまり、「セット内のタグごとに、それに添付されている各アイテムを探してください」ということです。繰り返しますが、「アイテム」は特異です。

今それを返しましょう:

.Return((tag, item) => new 
{
    Tag = tag.As<Tag>(),
    Items = item.CollectAs<Item>()
});

ここでは、各「アイテム」を取得して、それらを「アイテム」のセットに収集します。そのコードでの単数形と複数形の使用法は非常に具体的です。

結果のCypherテーブルは次のようになります。

-------------------------
| tag      | items      |
-------------------------
| red      | A, B, C    |
| blue     | B, D       |
| green    | E, F, G    |
-------------------------

最終コード:

var query = client
    .Cypher
    .StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)
    .Match("tag<-[:TaggedWith]-item")
    .Return((tag, item) => new
    {
        Tag = tag.As<Tag>(),
        Items = item.CollectAs<Item>()
    });

それはあなたに合うものではありませんSearchResult

オプション2

シナリオ:キーワードに一致するすべてのタグを取得してから、それらのタグのいずれかに一致するすべてのアイテムを取得する必要がありますが、2つをリンクする必要はありません。

Cypherクエリに戻りましょう:

START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN tag, item

これにより、次のようなCypher結果テーブルが生成されます。

--------------------
| tag      | item  |
--------------------
| red      | A     |
| red      | B     |
| red      | C     |
| blue     | B     |
| blue     | D     |
| green    | E     |
| green    | F     |
| green    | G     |
--------------------

これらのそれぞれを、関連のない単一のタグとアイテムのリストにまとめたいと考えています。

これを行うために使用できますcollect

START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN collect(tag) AS Tags, collect(item) AS Items

-----------------------------------------------------------------------------
| tags                                            | items                   |
-----------------------------------------------------------------------------
| red, red, red, blue, blue, green, green, green  | A, B, C, B, D, E, F, G  |
-----------------------------------------------------------------------------

ただし、これらの重複のすべては必要ないので、個別の重複を収集してみましょう。

START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN collect(distinct tag) AS Tags, collect(distinct item) AS Items

--------------------------------------------
| tags              | items                |
--------------------------------------------
| red, blue, green  | A, B, C, D, E, F, G  |
--------------------------------------------

Cypherが機能しているので、それを.NETに変換するのは簡単です。

var query = client
    .Cypher
    .StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)
    .Match("tag<-[:TaggedWith]-item")
    .Return((tag, item) => new
    {
        Tags = tag.CollectDistinct<Tag>(),
        Items = item.CollectDistinct<Item>()
    });

概要

  1. 常にサイファーから始めます
  2. 常にサイファーから始めます
  3. Cypherを使用している場合、.NETの実装はほぼ1対1である必要があります

問題?

VSをサポートしていないテキストボックスにこのコードをすべて入力しましたが、テストはしていません。何かがクラッシュした場合は、問題のページで完全な例外テキストとクエリを報告してください。ここでクラッシュを追跡するのは困難です。完全な例外テキスト、メッセージ、スタックトレースなどを使用せずにクラッシュを追跡すると、デバッグが困難になり、それ以外の場合に費やすことができる時間が短縮されるため、時間が消費されます。

于 2013-03-28T01:28:17.503 に答える