2010-03-17 2 views
0

Я перехожу из ADO.NET в Linq. Приложение представляет собой программу поиска по каталогам для поиска людей. Пользователям разрешено вводить критерии поиска в одно текстовое поле. Они могут отделять каждый термин пробелом или обертывать фразу в кавычки, например «место парковки», чтобы указать, что это один термин.Поиск набора данных с несколькими терминами с использованием Linq

За кулисами данные поступают из файла XML, в котором содержится около 90 000 записей и составляет около 65 мегабайт. Я загружаю данные в DataTable, а затем использую метод .Select с SQL-запросом для выполнения поиска. Запрос, который я передаю, построен из условий поиска, которые пользователь прошел. Я разделил строку из текстового поля на массив, используя регулярное выражение, которое разделит все на отдельный элемент, в котором есть пробел. Однако, если есть цитаты вокруг фразы, это становится ее собственным элементом в массиве. Затем я получаю один размерный массив с числом элементов x, который я перебираю для построения длинного запроса.

Я затем построить выражение поиска ниже:

 query = query & _ 
    "((userid LIKE '" & tempstr & "%') OR " & _ 
    "(nickname LIKE '" & tempstr & "%') OR " & _ 
    "(lastname LIKE '" & tempstr & "%') OR " & _ 
    "(firstname LIKE '" & tempstr & "%') OR " & _ 
    "(department LIKE '" & tempstr & "%') OR " & _ 
    "(telephoneNumber LIKE '" & tempstr & "%') OR " & _ 
    "(email LIKE '" & tempstr & "%') OR " & _ 
    "(Office LIKE '" & tempstr & "%'))" 

Каждый член будет иметь набор вышеупомянутого запроса. Если существует более одного термина, я помещаю AND между ними и строю другой запрос, как указано выше, со следующим термином. Я не уверен, как это сделать в Linq. До сих пор я правильно загрузил файл XML. Я могу найти его по определенным критериям, но я не уверен, как наилучшим образом реализовать поиск по нескольким терминам.

'this works but far too simple to get the job done 
    Dim results = From c In m_DataSet...<Users> _ 
    Where c.<userid>.Value = "XXXX" _ 
    Select c  

В приведенном выше коде также не используется оператор LIKE. Таким образом, частичные совпадения не работают. Похоже, что я бы хотел использовать это .Startswith, но это похоже только на Linq2SQL. Любые рекомендации будут оценены. Я новичок в Linq, поэтому, возможно, я пропустил простой способ сделать это.

файл XML выглядит так:

<?xml version="1.0" standalone="yes"?> 
<theusers> 

<Users> 
<userid>person1</userid> 
<nickname></nickname> 
<lastname></lastname> 
<firstname></firstname> 
<department></department> 
<telephoneNumber></telephoneNumber> 
<email></email> 
</Users> 

<Users> 
<userid>person2</userid> 
<nickname></nickname> 
<lastname></lastname> 
<firstname></firstname> 
<department></department> 
<telephoneNumber></telephoneNumber> 
<email></email> 
</Users> 

######## UPDATE ######## Ниже приводится полный рабочий раствор в VB благодаря нашему доброжелательному ответчику.


Вот запрос вы бы запустить:

Dim query = From d In m_DataSet.Descendants("Users") _ 
       Where d.ChildrenBeginWith(rezsplit) _ 
       Select d  


Вот метод расширения:

Public Module SearchEngine 
<System.Runtime.CompilerServices.Extension()> _ 
Public Function ChildrenBeginWith(ByVal parent As XElement, _ 
    ByVal ParamArray  searchTerms As String()) As Boolean 
    Dim ret As Boolean = False 
     Dim children = parent.Elements().ToList() 
     For Each searchTerm In searchTerms 
      ret = children.Any(Function(x) x.Value.StartsWith(searchTerm)) 
      If Not ret Then 
       Exit For 
      End If 
     Next 
     Return ret 
    End Function 
End Module 

ответ

1

Если вы просто хотите что-то, что работает с LINQ-to-XML вы может загрузить ваш xml в XDocument и выполнить следующий запрос. Он будет содержать любые значения дочерних узлов, которые начинаются с указанного текста.

Dim doc = XDocument.Parse("this is where your xml string goes") 
Dim query = From d In doc.Descendants("Users") _ 
      Where d.Elements().Any(Function(x As XElement) x.Value.StartsWith(tempStr)) _ 
      Select d 
For Each A In query 
    //Do Something 
Next 

Edit: К сожалению я не VB парень, так что следующий образец C# (я первоначально написал свой первый ответ в C#, но это было довольно легко для меня, чтобы преобразовать в VB).Я не знаю родного пути чисто делать то, что вы хотите, так что самый простой способ может быть вспомогательный метод или метод расширения, как в следующем:

Новый Запрос:

var query = from d in doc.Descendants("Users") 
      where d.ChildrenBeginWith(tempStr, tempStr2) 
      select d; 

метод расширения:

public static class Extension 
{ 
    public static bool ChildrenBeginWith(this XElement parent, params string[] searchTerms) 
    { 
     bool ret = false; 
     var children = parent.Elements().ToList(); 
     foreach (var searchTerm in searchTerms) 
     { 
      ret = children.Any(x => x.Value.StartsWith(searchTerm)); 
      if (!ret) 
       break; 
     } 
     return ret; 
    } 
} 
+0

Ничего себе, это здорово. Это значительно упрощает то, что у меня было в голове. Я полагаю, что осталось только выяснить несколько терминов. Если у меня есть только один поисковый запрос, ваше решение идеально. Мне нужно обрабатывать несколько. Поэтому, если пользователь передает Бобу 800-123-5555, тогда bob должен получить удар от псевдонима или имени, а номер телефона - номер телефона. –

+0

Хорошо. Я думаю, что я ближе, если я делаю Where d.Elements(). Any (Function (x As XElement) x.Value.StartsWith (tempStr)) AND _ Где d.Elements(). Any (Функция (x As XElement) x.Value.StartsWith (tempStr2)) Он перемещает меня в правильном направлении. Знаете ли вы, как это было бы чисто для X-термина? –

+0

Я не знаю, как правильно сделать то, что вы хотите изначально, поэтому я написал быстрый пример метода расширения, чтобы помочь вам (извините, что он находится в C#, но, надеюсь, он все равно поможет вам). –

Смежные вопросы