我有一个存储地址的表。此表有多个地址组件字段,例如地址编号,街道名称,方向,后缀,前缀,城市,州和邮政编码。 (编辑:此地址表包含以前由用户添加的地址。我希望他们来自同一个城镇,城市,州和国家。所以我确实保留了城市,州,国家和邮编从他们但不用于查询。)
我的应用程序是在数据库中找到用户输入的地址的完全匹配地址。如果没有完全匹配,则返回类似的地址。
用户输入或存储在数据库中的所有地址均由Google Map API标准化,以避免不匹配,例如1234 N Johnson St,1234 North Johnson St或1234 North John Street。
这是我正在使用的完全匹配的查询。由于存储和输入的地址均由Google地址API规范化,因此我可以获得完全匹配的结果。
var exactMatch = (from address in db.Addresses
where address.PrimaryAddressNumber == userInput.Number && address.Directional == userInput.Direction && address.Suffix == userInput.Suffix && address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
但是,如果没有完全匹配,那么我想给用户一个选项。据我所知,构建多个查询然后组合在一起。它按照我的预期工作,但时间太长了。
我喜欢
private IQueryable<IncidentSite> GetSimilarAddress(UserInput userInput)
{
var numberDirectionStreetname = (from address in db.Addresses
where address.PrimaryAddressNumber == userInput.Number && address.Directional == userInput.Direction && address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
var numberStreetname = (from address in db.Addresses
where address.PrimaryAddressNumber == userInput.Number && address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
var streetname = (from address in db.Addresses
where address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
var similarAddress = numberDirectionStreetname.Union(numberStreetname).Union(streetname);
return similarAddress;
}
正如您在similarAdddress
看到的那样,它将从dbo.Addresses
表中运行三个查询,但使用不同的where
语句,然后union
所有三个结果构建一个结果
我相信我所做的并不是找到类似地址的更聪明的方法。有没有什么好的方法可以构建一个更加简单和高效的查询?
修改 我想我不清楚为什么我必须有三个不同的查询,而不是一个。原因是为用户提供所有可能的结果。要进行更详细的说明,请参阅下文。
如果用户搜索'1234 North Johnson St'并且返回的确切匹配不完整,则执行以下步骤。
首先,在numberDirectionStreetname中,选择所有地址匹配'1234 North Johnson'。所以结果可以是1234 North Johnson + Boulevard / Street / Court / Way / Parkway /等。我希望它显示在列表的顶部,因为存在比后续组件更多的匹配地址组件。
其次,numberStreetname,选择与'1234 Johnson'匹配的所有地址。所以结果可以是1234 +南/北/东/西/等+强生+大道/街/法院/路/百汇等等
第三,街道名称,选择与'Johnson'匹配的所有地址。所以结果可以是9999 +南/北/东/西/等+强生+大道/街/法院/路/百汇等等
如果可能,我想在一个查询中执行此操作。这也是我的问题的一部分,不仅使它表现得更快,而且使它变得简单。但是,它必须是三个单独的查询,您将如何订购它们?如果我的逻辑不理想,你会怎么建议?
答案 0 :(得分:1)
不要担心直接比较。由于您需要一个紧密匹配列表,您只需根据匹配的组件数量对结果进行排名。
这是一个工作示例程序,可以根据地址的每个元素进行排名,根据排名计算整体排名和排名(排名越高,匹配越好)。
public class Program
{
private static readonly IEnumerable<Address> Addresses = new List<Address>
{
new Address{ Number = "1000", Direction = "North", Street = "Grand" },
new Address{ Number = "2000", Direction = "North", Street = "Broadway" },
new Address{ Number = "1000", Direction = "South", Street = "Main" },
new Address{ Number = "3000", Direction = "South", Street = "Grand" },
new Address{ Number = "2000", Direction = "East", Street = "Broadway" },
};
static void Main()
{
const string streetToMatch = "Broadway";
const string numberToMatch = "2000";
const string directionToMatch = "South";
var rankedAddresses = from address in Addresses
let streetRank = address.Street == streetToMatch ? 1 : 0
let numberRank = address.Number == numberToMatch ? 1 : 0
let directionRank = address.Direction == directionToMatch ? 1 : 0
let rank = streetRank + numberRank + directionRank
orderby rank descending
select new
{
Address = address,
Rank = rank
};
foreach (var rankedAddress in rankedAddresses)
{
var rank = rankedAddress.Rank;
var address = rankedAddress.Address;
Console.WriteLine($"Rank: {rank} | Address: {address.Number} {address.Direction} {address.Street}");
}
}
}
public class Address
{
public string Street { get; set; }
public string Number { get; set; }
public string Direction { get; set; }
}
<强>结果强>
等级:2 |地址:2000 North Broadway
等级:2 |地址:2000 East Broadway
等级:1 |地址:1000南主 等级:1 |地址:3000 Grand Grand
等级:0 |地址:1000 North Grand
答案 1 :(得分:1)
类似地址是什么意思?我认为通过类似的地址你的意思是同一个州和国家的类似地址?在这种情况下,您需要使用国家/地区过滤数据集,状态可能按国家/地区,州名第二,城市第三等顺序排列。您需要按此顺序缩小范围以减少正在使用的行。完成此操作后,您可以使用逻辑按街道,数字等查找类似地址。即使在这里,我建议使用自上而下的方法。
您的查询花费时间可能是由于查询必须使用的数据量。因此,过滤掉行是可行的方法。
此外,您可以避免发送多个查询并进行联合。您是否可以在一个查询中使用适当的AND OR条件一次完成所有操作。
我的意思是这样的。使用Inersect和Union的组合来重写您的逻辑。
using System;
using System.Linq;
using System.Collections.Generic;
namespace mns
{
public class Program
{
private static readonly IEnumerable<Address> Addresses = new List<Address>
{
new Address{ Number = "1234", Direction = "South", Street = "Main" },
new Address{ Number = "1234", Direction = "North", Street = "Broadway" },
new Address{ Number = "1234", Direction = "North", Street = "Grand" },
new Address{ Number = "1234", Direction = "South", Street = "Broadway" },
new Address{ Number = "34", Direction = "East", Street = "Broadway" },
};
public static void Main()
{
const string streetToMatch = "Broadway";
const string numberToMatch = "1234";
const string directionToMatch = "South";
var combinedAdrress = numberToMatch +" "+ streetToMatch + " "+ directionToMatch;
var rankedAddresses = from address in Addresses.Where(s=>numberToMatch== s.Number).Intersect(Addresses.Where(s=>directionToMatch==s.Direction)).Intersect(Addresses.Where(s=>streetToMatch == s.Street))
.Union(Addresses.Where(s=>numberToMatch== s.Number).Intersect(Addresses.Where(s=>streetToMatch == s.Street)))
.Union(Addresses.Where(s=>streetToMatch == s.Street))
select new
{
Address = address.Number + " " + address.Street+ " "+ address.Direction
};
Console.WriteLine("You are searching for: "+combinedAdrress);;
foreach (var rankedAddress in rankedAddresses)
{
var address = rankedAddress.Address;
Console.WriteLine(address);
}
}
}
public class Address
{
public string Street { get; set; }
public string Number { get; set; }
public string Direction { get; set; }
}
}
您可以更改输入值以进行测试。我得到的是
您正在寻找:1234 Broadway South
1234 Broadway South 1234 Broadway North 34 Broadway East
答案 2 :(得分:0)
为什么不首先获取所有streetNames,然后使用它作为主要列表从那里过滤掉?
var streetname = (from address in db.Addresses
where address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
var numberStreetname = (from address in streetname
where address.PrimaryAddressNumber == userInput.Number && address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
var numberDirectionStreetname = (from address in numberStreetname
where address.PrimaryAddressNumber == userInput.Number && address.Directional == userInput.Direction && address.StreetName == userInput.StreetName
select new IncidentSite
{
FullAddress = 'address components goes here'
});
答案 3 :(得分:0)
只是一个解决方案,而不是解决问题的确切代码。 通过应用或条件用户输入将所有地址放入列表中。然后从筛选列表中找出具有最大计数的地址。
例如:
List<Address> listOfAddress = new List<Address>{
new Address(){Street="street 1", FlatNum="15", City="Auckland"},
new Address(){Street="street 2", FlatNum="20", City="Napier"},
new Address(){Street="street 1", FlatNum="15", City="Hamilton"}
};
string userInputStree = "street 1";
string userInputFlatnum = "15";
string userInputCity = "Whangrey";
var addressList = (from address in listOfAddress
where address.Street == userInputStree || address.City==userInputCity || address.FlatNum == userInputFlatnum
select address.FlatNum + ", " + address.Street + ", " + address.City
).ToList();
//from address List find the address which has maximum count