搜索产品,即使代码拼写错误
本文关键字:代码 错误 搜索 | 更新日期: 2023-09-27 18:36:44
好吧,伙计们,我在这里遇到了一个树桩。
基本上我遇到的问题是,当人们搜索某些东西时,他们输入了错误的代码,因为很多时候他们涉及多个 0,例如在搜索时:K00000WEFLZ
他们输入错误 0,然后产品结果返回什么都没有,我基本上是希望尝试让它让搜索检查搜索是否在字母后包含一定数量的 0"K"(因为 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;
}
模糊的逻辑,一定喜欢它。 我这样做的方式,并没有说明它应该如何完成,但我会尽我最大的努力,就是从搜索字符串本身构建一个正则表达式。
将正则表达式生成器视为自定义构建的压缩操作。 从您的字符数组开始并从中构建正则表达式搜索,任何时候您在一行中找到 2 个相同的字符,将第二个(并忽略第二个以外的任何其他字符)替换为"+"字符,然后使用正则表达式而不是完全字符串匹配运行结果搜索。
K00000WEFLZ
会变成K0+WEFLEZ
,并匹配K,1个或多个0,WEFLEZ。 该算法需要对任何重复的字符执行此操作,因此可能会使其有点愚蠢。 像KK000WWLEFF22
这样的东西会K+0+W+LEF+2+
. 搜索字符串并没有那么好,并且可能匹配很多您不想要的东西......但有效。 或者您可以将其限制为仅替换 0 或 0。 等等等等...无论什么最终效果最好。
我推荐的另一种方法是实时过滤。 但它的有用性更多地取决于预期的正常功能。 用户键入值会更常见,还是更常见,或者他们从其他地方复制/粘贴值会更常见。 在第二种情况下,实时过滤是完全无用的。 否则。。。重新筛选每个按键或文本更改事件上的列表。 至少那时他们可能会知道整个列表何时消失,因为输入了额外的 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);