Linq Query to compare if collection contains list of string - vb.net

Im fairly new to Linq and am trying to write a search results query.
We use a tagging system for our help desk and Im trying to return all cases that contain tags or children of TAGS selected from a drop down list.
I am using a path comparison to find any children tags which works well when there is only 1 tag selected. This is my code for when multiples tags are selected but it is not working. Can you point me in the right direction?
Single Tag Selection (working)
Dim tagpath = uxTags.SelectedItem.Text
lnqCases = From i In lnqCases Where i.HelpDeskTagItems.Any(Function(x) x.Path.StartsWith(tagpath))
Multi Tag Selection (not working)
Dim tagpaths As New List(Of String)
For Each i In TagList.SelectedItems
tagpaths.Add(i.ToString)
Next
lnqCases = From i In lnqCases Where i.HelpDeskTagItems.Any(Function(x) x.Path.StartsWith(tagpaths.Any))

Reverse the logic, check for the Path within the list
lnqCases = From i In lnqCases Where i.HelpDeskTagItems.Any(Function(x) tagpaths.Contains(x.Path))
Or to continue the StartsWith logic
lnqCases = From i In lnqCases Where i.HelpDeskTagItems.Any(Function(x) Test.Exists(Function(m) m.StartsWithPath(x)))

Related

Convert For-Each into a LINQ query for adding items in list and check wehter list contains the item already

I would like to convert ForEach to LINQ. Currently I'm using these two parts
If TypeOf e.FilterPopup Is RadListFilterPopup Then
Dim ePopup As RadListFilterPopup = DirectCast(e.FilterPopup, RadListFilterPopup)
Dim childList As New List(Of Object)()
For Each row As GridViewRowInfo In Me.grdCNCFilesRad.ChildRows
Dim value = row.Cells(e.Column.Index).Value
If Not childList.Contains(value) Then
childList.Add(value)
End If
Next
Dim newPopup As New RadListFilterPopup(e.Column)
For Each item As System.Collections.ArrayList In ePopup.MenuTreeElement.DistinctListValues.Values
If Not childList.Contains(item(0)) Then
newPopup.MenuTreeElement.DistinctListValues.Remove(item(0).ToString())
End If
Next
e.FilterPopup = newPopup
End If
How can I do the same with a LINQ query?
I don't know what your variable grdCNCFilesRad is type of, but I assume it is no .NET type. But when I read ChildRows then I can be sure that this is some sort of enumeration (somewhere in it's inheritance tree must be the interface IEnumerable).
So you can include System.Linq and apply a AsQueryable() at your ChildRows.
The rest is just a little bit of Linq (Select, Where, ToList()). That's it!
Edit:
The first part should be solved by this:
Dim childList =
Me.grdCNCFilesRad.ChildRows
.AsQueryble()
.Select(Function(row) row.Cells(e.Column.Index).Value)
.Distinct()
There is no need of converting ForEach with Linq if you go for performance issues.
Your existing foreach code looks good.
Note: Don't think Linq is better compared to for-each in performance.

Display particular part of website

I'm going to create a tool which displays webpage rank in VB.NET.
For that I use
Dim str As String = New WebClient().DownloadString(("http://www.alexa.com/siteinfo/" + TextBox1.Text))
And I just want the Global Rank of that url which I provided in textbox1.text
Like here, I provide example.com to check its Alexa global rank:
I just need to display the global ranking number in my VB form.
Plz take a look at this:
Sub Main
Dim str As String = New WebClient().DownloadString(("http://www.alexa.com/siteinfo/example.com"))
Dim pattern = "a href=""/siteowners/certify.+?\>(?<rank>[0-9,]+?)\<\/a\>"
Dim r = new Regex(pattern, RegexOptions.IgnoreCase)
Dim m As Match = r.Match(str)
If m.Success Then
Debug.Print("Global rank " + m.Groups(1).ToString())
m = m.NextMatch()
Debug.Print("Usa rank " + m.Groups(1).ToString())
Else
Debug.Print("Failed")
End If
End Sub
On my computer answer is
Global rank 8,893
Usa rank 10,060
This code need better error handling but I guess it is ok as a proof of concept.
UPD. Some words on how it works:
The code above uses regular expressions (please take a look at this link to get started) to parse web page and extract the values you need.
On the screenshot you provided one can see that the ranks are stored in html <a> tag, which I identify by its href attribute, since it is the only <a> tag on the page, whose href attribute starts with string "/siteowners/certify". Hence, my regular expression matches for inner text of that tag and extracts it into match group.

HtmlAgilityPack - Get only the first match

Im new to HtmlAgilityPack and i cant figure out how to stop the search after the first match has been found.
Dim site As HtmlAgilityPack.HtmlWeb = New HtmlWeb()
Dim document As HtmlAgilityPack.HtmlDocument = site.Load("website")
For Each table As HtmlNode In document.DocumentNode.SelectNodes("//td[#class='forum_thread_post']//a[#href]")
ListBox1.Items.Add(table.InnerText)
Next
The problem is that the website contains many td[#class='forum_thread_post' nodes and i only need the first one. I experimented with SelectSingleNode too, but i couldnt even get that to work but im thinking that is the way to do it? If getting the single match to a textbox is better/easier i would want that.
Here is a picture: http://oi42.tinypic.com/25fmwr5.jpg
I want to get the a title or a alt from the picture
What was wrong with SelectSingleNode?
Dim table = document.DocumentNode.SelectSingleNode("//td[#class='forum_thread_post']//a[#href]")
ListBox1.Items.Add(table.InnerText)
If the InnerText could be empty:
Dim tables = document.DocumentNode.SelectNodes("//td[#class='forum_thread_post']//a[#href]")
Dim firstNotEmpty = tables.FirstOrDefault(Function(t) Not String.IsNullOrWhiteSpace(t.InnerText))

Query results don't match NumFound when using SolrNet with VB.NET

I have implemented SolrNet in a VB.NET web site and it's working perfectly with one exception. My results object may tell me that 10 matching "documents" have been found but the collection only contains 9.
My collection always contains 1 less than the NumFound property states. I have run the queries directly through my Solr instance and I know that the NumFound property is reflecting the correct value. Having reviewed the returned documents I can see that the first document in each result set is missing from my collection i.e. the one at position 0.
This seems like a problem connected to a zero indexed collection.
I can't see that I'm doing anything wrong and suspect that this is a bug. Has anyone else experienced this or can you suggest where I may have gone wrong?
Source code is as follows
Private Prods As New SolrQueryResults(Of BLL.solrProduct)
Dim solr As ISolrOperations(Of BLL.solrProduct) = ServiceLocator.Current.GetInstance(Of ISolrOperations(Of BLL.solrProduct))()
Dim SolrQueryOptions As New SolrNet.Commands.Parameters.QueryOptions() With {.Stats = New StatsParameters(), .Start = PagingCurrent, .Rows = PagingSize, .Facet = New FacetParameters() With { _
.MinCount = 1, .Queries = New SolrNet.ISolrFacetQuery() {New SolrFacetFieldQuery("brand")}}}
SolrQueryOptions.Stats.AddField("selling_price")
SolrQueryOptions.FilterQueries.Add(New SolrQueryByField("brand", "puma"))
Prods = solr.Query("shirt", SolrQueryOptions)
PagingTotal = Prods.NumFound 'This returns 10
lv_prods.DataSource = Prods
lv_prods.DataBind() 'This renders 9 items
Solr pagination is zero-based, i.e. the first item corresponds to Start=0

Building a dynamic LINQ query

I have a listbox which users can select from a list if Towns, I want to be able to build a LINQ query based on the selected items in the list e.g.
Dim ddlTowns As ListBox = CType(Filter_Accommodation1.FindControl("ddlTowns"), ListBox)
If Not ddlTowns Is Nothing Then
For Each Item In ddlTowns.Items
If Item.Selected Then
'// Build query
End If
Next
End If
I have researched LinqKit as it appears to be able to do what I need but I cannot after hours of trying make any headway. I cannot find anything in VB which translates in anything meaningful or usable.
Just had a Eureka moment and rather than using predicate I came up with this...
Private Function Filter_Accommomdation_QueryBuilder() As IEnumerable
Dim ddlTowns As ListBox = CType(Filter_Accommodation1.FindControl("ddlTowns"), ListBox)
Dim myList As New List(Of String)
If Not ddlTowns Is Nothing Then
For Each Item In ddlTowns.Items
If Item.Selected Then
myList.Add(Item.value)
End If
Next
End If
Dim Filter_Query = _
From c In InitialQuery _
Where myList.ToArray.Contains(c.MyData.element("townvillage").value) _
Select c
Return Filter_Query
End Function
As a note I'm using c.MyData as the nature of InitialQuery demands a number of structured fields (the query is reused from various tables which by poor design aren't very consistant).
Check out this question - contains some useful VB examples for you: Using PredicateBuilder with VB.NET