1

わかりました、私はここで切り株にいます。

基本的に私が抱えている問題は、人々が何かを検索しているとき、多くの場合、複数の 0 が含まれているため、コードをミスタイプしているK00000WEFLZことです。私は基本的に、検索に文字「K」の後に一定量の0が含まれているかどうかを検索がチェックするようにしようとしています(Kには常に10以上のID番号と少なくとも4〜5個の0があるため)。検索操作中に「*」に置き換えられ、問題をどれだけ間違って入力しても製品を見つけることができます。

カスタムクラスを作成し、これのデフォルトをオーバーライドする必要があることを認識しています(ただし、これの多くはアクセスできません/プライベートです)。デフォルトの検索パターンは変更できないため、これはすべての人に変更されます。この特定のサイトのためにそれをしたい。

また、これの最初または最後にワイルドカードを使用することはできません。これは、膨大なカタログがあるため、マイルが多くの結果に一致するためです。

私の知る限り、これはデフォルト ロジックのクラスで検索を処理するコードです。

protected virtual IList<Product> CreateCustomCollection()
{
        var list = new List<Product>();

        switch (mode)
        {
            case ProductRepeaterMode.Search:

                if (Page.Request.QueryString["search"] != null && Page.Request.QueryString["search"].Length != 0)
                {
                    bool[] customString = new bool[5] { SearchCustomString1, SearchCustomString2, SearchCustomString3, SearchCustomString4, SearchCustomString5 };
                    IList<Product> results = Fabric.ObjectProvider.Get<IProductSearchCommand>().Search(Page.Request.QueryString["search"], out searchWords, IncludeSkus, IsPublicFacing, customString, CoreHttpModule.Session);

                    var retailOrder = WebStoreManager.CurrentOrder as IRetailOrder;
                    var accountOrder = WebStoreManager.CurrentOrder as IAccountOrder;

                    IList<Product> productsToRemove = new List<Product>();
                    IList<Product> productsToAdd = new List<Product>();

                    foreach (var product in results)
                    {
                        if (hideRestrictedProducts)
                        {
                            if (retailOrder != null)
                            {
                                if (!product.CanBePurchasedByRetailCustomer || product.AgentOnly)
                                    productsToRemove.Add(product);
                            }
                            else
                            {
                                if (accountOrder != null)
                                {
                                    var add = false;

                                    if (product.CanBePurchasedOnAccount)
                                        add = true;

                                    if (product.AgentOnly)
                                    {
                                        if (accountOrder.Agent != null)
                                            add = true;
                                        else
                                            add = false;
                                    }

                                    if (!add)
                                        productsToRemove.Add(product);
                                }
                            }
                        }

                        // Replace SKUs with lines
                        if (resolveSkusToLines)
                        {
                            var sku = product.Role as SkuProductRole;
                            if (sku != null)
                            {
                                productsToRemove.Add(product);
                                if (sku.Owner != null && sku.Owner.Product != null)
                                {
                                    var line = sku.Owner.Product;
                                    if (!results.Contains(line) && !productsToAdd.Contains(line))
                                        productsToAdd.Add(line);
                                }
                            }
                        }
                    }

                    foreach (Product product in productsToAdd)
                    {
                        results.Add(product);
                    }

                    foreach (Product product in productsToRemove)
                    {
                        results.Remove(product);
                    }

                    foreach (var result in results)
                        list.Add(result);
                }
                break;
        }
        return list;
    }
4

1 に答える 1

2

ファジーロジック、大好きです。私がこれを行う方法は、実際にどのように行うべきかについて多くを語っていませんが、私自身の最善を尽くしますが、検索文字列自体から正規表現を構築することです.

カスタム構築された圧縮操作のように正規表現ビルダーを扱います。文字配列から始めて、そこから正規表現検索を作成します。連続して2つの同一の文字が見つかったら、2番目を「+」文字に置き換えて(2番目以降は無視して)、正規表現を使用して結果の検索を実行します正確な文字列一致ではなく。

K00000WEFLZになりK0+WEFLEZ、K、1 つ以上の 0、WEFLEZ に一致します。アルゴリズムは、繰り返されるすべての文字に対してこれを行う必要があるため、少しばかげている可能性があります。のようなものKK000WWLEFF22が来るでしょうK+0+W+LEF+2+。検索文字列としてはそれほど優れているわけではなく、多くの不要なものに一致する可能性がありますが、効果的です。または、0 または 0 のみを置き換えるように制限することもできます。などなど...最終的に最適に機能するものは何でも。

私がお勧めするもう 1 つの方法は、ライブ フィルタリングです。しかし、その有用性は、予想される通常の機能に大きく依存します。ユーザーが値を入力するのが一般的ですか、それとも他の場所からコピー/貼り付けするのが一般的ですか? 2 番目のケースでは、ライブ フィルタリングはまったく役に立ちません。それ以外の場合は...すべての keyPress または TextChanged イベントでリストを再フィルター処理します。少なくとも、余分な 0 を入力したためにリスト全体が消えた時期を知ることができるかもしれません。

編集 - コードサンプルを追加

private string RegStringZipper(string searchString)
    {
        StringBuilder sb = new StringBuilder();
        char lastChar = new char();
        bool plusFlag = false;
        foreach (char c in searchString)
        {
            if (sb.Length == 0)
            {
                sb.Append(c);
                lastChar = c;
            }
            else
            {
                if (lastChar == c)
                {//we have a repeating character
                    //Note: Here is also where if you only wanted to filter a specific character, like 0, you would check for it.
                    if (!plusFlag)
                    {//we have not already added the +
                        sb.Append('+');
                        plusFlag = true;
                    }
                    //else do nothing, skip the characer
                }
                else
                {
                    sb.Append(c);
                    plusFlag = false;
                    lastChar = c;
                }
            }
        }
        return sb.ToString();
    }

私があなたのコードにどこに収まるかについては...それは本当にその検索機能が実際にどのように機能するかに依存します、それは私が今まで遊んだことのないものです...そういえば...それが機能する場合、見た目はそれがうまくいくように、上記のコードで「+」を「*」と交換してください....

if (Page.Request.QueryString["search"] != null && Page.Request.QueryString["search"].Length != 0)
            {
                bool[] customString = new bool[5] { SearchCustomString1, SearchCustomString2, SearchCustomString3, SearchCustomString4, SearchCustomString5 };
                string SearchString = RegStringZipper(Page.Request.QueryString["search"]);
                //please note, given that I dont know what FabricProvider.Search works on, I dont actually know that this works as intended.
                IList<Product> results = Fabric.ObjectProvider.Get<IProductSearchCommand>().Search(SearchString, out searchWords, IncludeSkus, IsPublicFacing, customString, CoreHttpModule.Session);
于 2012-06-08T15:35:09.577 に答える