12

これらのキーワードに関連するすべての広告を返す一連のキーワードに基づいて検索を行う必要があります。結果は、各カテゴリの広告数を含むカテゴリのリストです。

検索は KeywordSearch テーブルで行われます。

public class KeywordSearch
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Keyword Keyword { get; set; }
}

キーワード テーブルの場所:

public class Keyword
{
    public int Id { get; set; }
    public string Name { get; set; }
}

広告は、次の表を使用してキーワードに関連付けられています。

public class KeywordAdCategory
{
    [Key]
    [Column("Keyword_Id", Order = 0)]
    public int Keyword_Id { get; set; }

    [Key]
    [Column("Ad_Id", Order = 1)]
    public int Ad_Id { get; set; }

    [Key]
    [Column("Category_Id", Order = 2)]
    public int Category_Id { get; set; }
}

最後に、カテゴリ テーブル:

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

例:

  • キーワード: 「メルセデス・ベンツ」と「GLK」
  • キーワード検索: キーワード「Mercedes-Benz」の場合は「Mercedes」と「Benz」、キーワード「GLK」の場合は「GLK」
  • カテゴリ: 「乗用車」と「トラック」
  • 広告: 車 - メルセデスベンツ GLK トラック - メルセデスベンツ シタン

    「メルセデス・ベンツ」を検索すると、次のようになります。

    • 車: 1
    • トラック: 1

    「Mercedes-Benz GLK」を検索すると、次のようになります。

    • 車: 1

    「メルセデス シタン」で検索すると、次のようになります。

    • トラック: 1

私が今まで得たもの:

var keywordIds = from k in keywordSearchQuery
                    where splitKeywords.Contains(k.Name)
                    select k.Keyword.Id;

var matchingKac = from kac in keywordAdCategoryQuery
                    where keywordIds.Distinct().Contains(kac.Keyword_Id)
                    select kac;

var addIDs = from kac in matchingKac
             group kac by kac.Ad_Id into d
             where d.Count() == splitKeywords.Count()
             select d.Key;

var groupedKac = from kac in keywordAdCategoryQuery
                    where addIDs.Contains(kac.Ad_Id)               <--- EDIT2
                    group kac by new { kac.Category_Id, kac.Ad_Id };

var result = from grp in groupedKac
                group grp by grp.Key.Category_Id into final
                join c in categoryQuery on final.Key equals c.Id
                select new CategoryGetAllBySearchDto
                {
                    Id = final.Key,
                    Name = c.Name,
                    ListController = c.ListController,
                    ListAction = c.ListAction,
                    SearchCount = final.Count()
                };

問題は、すべてのキーワードに一致する広告だけを取得できないことです。

編集:

「Mercedes-Benz」のようにキーワードが 2 つ以上の KeywordSearch で構成されている場合、「where d.Count() == splitKeywords.Count()」の行は失敗します。メルセデスベンツ"

ヘルプはありますか?

4

7 に答える 7

2

これは直接的な答えではないかもしれませんが、このような「複数のパラメーター検索」の状況では、何も忘れて単純なことをします。たとえば、自動車メーカー、CategoryId、MillageMax、Price で検索します。

var searchResults = from c in carDb.Cars
where (c.Manufacturer.Contains(Manufacturer) || Manufacturer == null) &&
                 (c.CategoryId == CategoryId || CategoryId == null) &&
                    (c.Millage <= MillageMax || MillageMax== null) &&
                          (c.Price <= Price  || Price == null) 
select c

パラメータのいずれかが である場合、null式全体を括弧で囲むことにより、含まれている行がキャンセルされるTrueため、検索に参加しなくなります

于 2013-11-12T07:49:37.137 に答える
1

独自の検索エンジンを作ろうとすると、おそらく失敗します。Lucene を試してみませんか。リンクはhttp://lucenenet.apache.org/です。乾杯

于 2013-11-14T18:28:18.657 に答える
0

私はこれなどをコンパイルチェックしていないので、微調整が必​​要かもしれませんが、これらの行に沿って何かを探しています.

var matchingKac = keywordIds.Distinct().ToList()
    .Aggregate(
        keywordAdCategoryQuery.AsQueryable(),
        (q, id) => q.Where(kac => kac.Keyword_Id == id));

「 から始めてkeywordAdCategoryQuery、キーワードごとに、.Where()そのキーワードが含まれている必要があるという条件を追加します。読みにくいfor場合は、ループで同じことを行うことができます。Aggregate

于 2013-11-05T18:36:29.783 に答える
0

回答を投稿しました: https://github.com/n074v41l4bl34u/StackOverflow19796132お 気軽にレビューしてください。

これが最も重要なスニペットです。


と:

internal class SearchDomain
{
  public List<Keyword> Keywords { get; set; }
  public List<Category> Categories { get; set; }
  public List<KeywordAdCategory> KeywordAdCategories { get; set; }
}

それから:

private static char[] keywordPartsSplitter = new char[] { ' ', '-' };

internal static Dictionary<Category, Dictionary<int, List<KeywordAdCategory>>> FromStringInput(string searchPhrase, SearchDomain searchDomain)
{
  var identifiedKeywords = searchPhrase
    .Split(keywordPartsSplitter);

  var knownKeywordParts = identifiedKeywords
    .Where
    (ik =>
      searchDomain
      .Keywords
      .SelectMany(x => x.GetKeywordParts())
      .Any(kp => kp.Equals(ik, StringComparison.InvariantCultureIgnoreCase))
    );

  var keywordkSearches = knownKeywordParts
    .Select((kkp, n) => new KeywordSearch()
    {
      Id = n,
      Name = kkp,
      Keyword = searchDomain
        .Keywords
        .Single
        (k =>
          k.GetKeywordParts()
            .Any(kp => kp.Equals(kkp, StringComparison.InvariantCultureIgnoreCase))
        )
    });

  var relevantKeywords = keywordkSearches
    .Select(ks => ks.Keyword)
    .Distinct();

  var keywordAdCategoriesByCategory = searchDomain.Categories
    .GroupJoin
    (
      searchDomain.KeywordAdCategories,
      c => c.Id,
      kac => kac.Category_Id,
      (c, kac) => new { Category = c, AdKeywordsForCategory = kac }
    );

  var relevantKeywordAdCategories = keywordAdCategoriesByCategory
    .Where
    (kacbk =>
      relevantKeywords
        .All
        (rk =>
          kacbk
            .AdKeywordsForCategory
            .Any(kac => kac.Keyword_Id == rk.Id)
        )
    );

  var foundAdsInCategories = relevantKeywordAdCategories
    .ToDictionary
    (rkac =>
      rkac.Category,
      rkac => rkac.AdKeywordsForCategory
        .GroupBy(g => g.Ad_Id)
        .ToDictionary(x => x.Key, x => x.ToList())
    );

  return foundAdsInCategories;
}

それはまさにあなたが望むことをしますが、キーワードがサブキーワードに割り切れることについて何か怪しいものを見つけます. 繰り返しますが、おそらくそれは単なるネーミングです。

于 2013-12-15T21:07:48.087 に答える
0

私は今、解決策を持っていると思います。これは、前の質問といくつかの仮定に基づいています。

  1. キーワードは、「Mercedes-Benz GLK」、「Mercedes-Benz Citan」などの完全な名前です。
  2. キーワード検索は、「Mercedes-Benz GLK」の場合は「Mercedes」「Benz」「GLK」、「Mercedes-Benz Citan」の場合は「Mercedes」「Benz」「Citan」
  3. 「Mercedes-Benz GLK」は「Car」、「Mercedes-Benz Citan」は「Truck」

これら3つの前提を念頭に置いて、私はそれを言うことができます

var keywordIds = from k in keywordSearchQuery
                 where splitKeywords.Contains(k.Name)
                 select k.Keyword.Id;

が犯人であり、以下のすべてのクエリはそれに依存しています。このクエリは、検索文字列に任意の単語を含むすべてのキーワードを検索します。

例: 検索文字列「Mercedes-Benz GLK」を指定すると、「Mercedes」、「Benz」、「GLK」に分割されます。クエリは、"Mercedes-Benz GLK" と "Mercedes-Benz Citan" の両方で "Mercedes" と "Benz" を検索します。
「Mercedes-Benz GLK」を「Mercedes-Benz Citan」と一致させたくないのは明らかだと思います。

解決策は、すべての splitKeywords を任意の Keywordsearch と一致させ、適切な Keyword を返すようにクエリに指示することです。

var keywordIds = keywordSearchQuery
                 .GroupBy(k => k.Keyword.Id)
                 .Where(g => splitKeywords.All(w => 
                                               g.Any(k => k.Name.Contains(w))))
                 .Select(g => g.Key);

addIds に関しては、それを変更するとうまくいくvar addIDs = matchingKac.Select(ad => ad.Ad_Id).Distinct();はずです。または、matchingKac が addIds でのみ必要な場合は、次のように変更できます。

var matchingKac = (from kac in keywordAdCategoryQuery
                   where keywordIds.Distinct().Contains(kac.Keyword_Id)
                   select kac.Ad_Id).Distinct();

addIds を削除します。

于 2013-11-07T14:13:30.500 に答える