Trying to compare the two strings inside the linq query - c#

I am trying to check the equality on two strings using the EF Functions like a method, but it is failing somehow and getting null on spaces.
The two strings are like as below, Here you can observe the only difference is the case for SPACE
the displayName is L1-008-5 SPACE and I have stored Displayname in space identity object as like this L1-008-5 Space
L1-008-5 SPACE and L1-008-5 Space
Here is the code
var space = dbContext.Spaces.SingleOrDefault(a => EF.Functions.Like(a.SpaceIdentity.DisplayName, displayName));
and I tried the below options as well
dbContext.Spaces.SingleOrDefault(s => s.SpaceIdentity.DisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase));
dbContext.Spaces.SingleOrDefault(s => string.Equals(s.SpaceIdentity.DisplayName,displayName, StringComparison.OrdinalIgnoreCase));
None of the above are working and getting null on spaces.
Could anyone please point me in the right direction where I am doing wrong with the above comparison.
Many thanks in advance!

Assuming you are using the Npgsql.EntityFrameworkCore.PostgreSQL provider for EF Core, you should have access to the ILike method which is a case-insensitive LIKE. That means you are able to use this code:
var space = dbContext.Spaces
.SingleOrDefault(a =>
EF.Functions.ILike(a.SpaceIdentity.DisplayName, displayName));
// ^^^^^

Related

Elastic query to search eliminating spaces from mongodb data C#

I wanted to know if there is a way to search MongoDB data excluding space. My MongoDB has data such as -
"Element":"Ele1"
"Element":"Ele2"
"Element":"Ele 3"
And my search query has string excluding space i.e "Ele1,Ele2,Ele3". So When I pass "Ele3" to my search query it does not return any result. I am using ElasticSearch.net nuget. My code is something like this -
var elResp = await data.MultiSearchAsync(m => m
.Query(q => q
.Nested(n => n
.Path("Element")
.Query(qq => qq
.Bool(b => b
.Must(m1 => m1
.Term("Element.keyword", "Ele1")))))))
Is there anything I can do or I have to create an extra field in MongoDb which saves Element Value without space. So I can perform check from that. Thanks
You'd achieve the best performance by creating extra field without spaces, however in MongoDB you can just use $regex to match both fields with and without spaces.
db.collection.find({ "Element": { $regex: /Ele\s*3/ } })
where \s is a whitespace and *means zero or more occurences. The more spaces you predict, the more you should consider adding a field without any spaces (because of performance), but /E\s*l\s*e\s*3/ will be still working for this case.

Sitecore Lucene index search term with space match same word without space

This seems so simple that I'm convinced I must be overlooking something. I cannot establish how to do the following in Lucene:
The problem
I'm searching for place names.
I have a field called Name
It is using Lucene.Net.Analysis.Standard.StandardAnalyzer
It is TOKENIZED
The value of Name contains 1 space in the value: halong bay.
The search term may or may not contain an extra space due to culturally different spellings or genuine spelling mistakes. E.g. ha long bay instead of halong bay.
If I use the term halong bay I get a hit.
If I use the term ha long bay I do not get a hit.
The attempted solution
Here's the code I'm using to build my predicate using LINQ to Lucene from Sitecore:
var searchContext = ContentSearchManager.GetIndex("my_index").CreateSearchContext();
var term = "ha long bay";
var predicate = PredicateBuilder.Create<MySearchResultItemClass>(sri => sri.Name == term);
var results = searchContext.GetQueryable<MySearchResultItemClass>().Where(predicate);
I have also tried a fuzzy match using the .Like() extension:
var predicate = PredicateBuilder.Create<MySearchResultItemClass>(sri => sri.Like(term));
This also yields no results for ha long bay.
How do I configure Lucene in Sitecore to return a hit for both halong bay and ha long bay search terms, ideally without having to do anything fancy with the input term (e.g. stripping space, adding wildcards, etc)?
Note: I recognise that this would also allow the term h a l o n g b a y to produce a hit, but I don't think I have a problem with this.
A TOKENIZED field means that the field value is split by a token (space in that case) and the resulting terms are added to the index dictionary. If you index "halong bay" in such a field, it will create the "halong" and "bay" terms.
It's normal for the search engine to fail to retrieve this result for the "ha long" search query because it doesn't know any result with the "ha" or "long" terms.
A manual approach would be to define all the other ways to write the place name in another multi-value computed index field named AlternateNames. Then you could issue this kind of query: Name==query OR AlternateNames==query.
An automatic approach would be to also index the place names without spaces in a separate computed index field named CompactName. Then you could issue this kind of query: Name==query OR CompactName==compactedQueryWithoutSpaces
I hope this helps
Jeff
Something like this might do the trick:
var predicate = PredicateBuilder.False<MySearchResultItemClass>();
foreach (var t in term.Split(' '))
{
var tempTerm = t;
predicate = predicate.Or(p => p.Name.Contains(tempTerm));
}
var results = searchContext.GetQueryable<MySearchResultItemClass>().Where(predicate);
It does split your input string, but I guess that is not 'fancy' ;)

Sitecore ContentSearch LIKE operator fails on non-alpha characters

I am attempting to implement a custom search in Sitecore 7.5 using the ContentSearch.LINQ library and making use of fuzzy search. For strings containing only alpha characters and whitespace, it works like a charm, i.e. "cxlcium" will return results for "calcium." However, the end goal of this is more to protect against common misspellings - "St Johns Wort" should return items with "St. John's Wort." Interestingly enough, "St. Johns Wort" will return zero results, and an exact match will throw an exception due to the single quote (I'm assuming that may need to be escaped, though it works without issue on StartsWith or Contains type searches). I have tried moving the minimumSimilarity value up and down to no avail.
For what it's worth, this is also passing through to a Coveo index rather than Lucene.
Thanks in advance for any insight.
Code is as follows:
var productResults = context.GetQueryable<SearchResultItem>()
.Where(x => x["productname"].Like(searchQuery, .7f)
.Take(10)
.OrderBy(x => x["productname"])
.GetResults();
You might be better off using the phonetic match extension provided by Coveo. More info here:
https://developers.coveo.com/display/public/SC201409/Coveo+LINQ+Extensions

How to check if returned array has atleast two elements?

Here is my code:-
Repository.DB.Table01Repository.AsQueryable().Where(item => (item.Name.Split(' ')[1] == null)).ForEach(items => _VerifyList.Add(items.Name.Trim()));
I split 'Name' by ' ' and if it does not have second element, I need those records.
Thanks..
Since Split will produce two or more elements if the Name contains at least one space, you can write it as follows:
Repository.DB.Table01Repository.AsQueryable()
.Where(item => !item.Name.Contains(" "))
.ForEach(items => _VerifyList.Add(items.Name.Trim()));
There's no need to actually perform the Split.
In addition, Contains can be mapped to SQL (it is one of the CLR methods that map to canonical LINQ functions) which means that the query will execute successfully on your database. Other methods (like Split itself) cannot be used when querying a database through IQueryable, and would cause a runtime exception to be thrown.
You want to be wary of white space in this scenario. "abcd ".Split().Count() will return 2 due to the whitespace character at the end. To avoid this use the Trim() method to remove leading and trailing white spaces before splitting like this:
if(item.Name.Trim().Split() > 1)
{
// Do stuff
}
or in a Where clause:
.Where(item => (item.Name.Trim().Contains(" ")))

String-parsing-fu: Can you help me find a way to retrieve this value?

I need to somehow detect if there is a parent OU value, and if there is retrieve it.
For example, here there is no parent:
LDAP://servera/OU=Santa Cruz,DC=contoso,DC=com
But here, there is a parent:
LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com
So I would need to retrieve that "Ventas" string.
Another example:
LDAP://servera/OU=Contabilidad,OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com
I would need to retrieve that "Ventas" string as well.
Any suggestions on how to tackle this?
string ldap = "LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com";
Match match = Regex.Match(ldap, #"LDAP://\w+/OU=(?<toplevelou>\w+?),OU=");
if(match.Success)
{
Console.WriteLine(match.Result("${toplevelou}"));
}
I'd find the first occurrence of OU=... and get it's value. Then I'd check if there was another occurrence after it. If so, return the value I've got. If not, return whatever it is you want if there's no parent (String.Empty, or, null, or whatever).
You could also use a regular express like this:
var regex = new Regex(#"OU=(.*?),");
var matches = regex.Matches(ldapString);
Then check how many matches there are. If >1 return the captured value from the first match.
Update
The regex above needs to be improved to allow the case where there's an escaped comma (\,) in the LDAP string. Maybe something like:
var regex = new Regex(#"OU=((.*?(\\\,)+?)+?),");
That may be broken, and there may be simpler way to do the same thing. I'm not a regex wizard.
Another Update
Per Kimberly's comment below the regex should be #"OU=((?:.*?(?:\\\,)*?)+?),".
Call me crazy, but I 'd do it this way (hey ma, look, an one-liner!):
var str = "LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com";
var result = str.Substring(str.LastIndexOf('/') + 1).Split(',')
.Select(s => s.Split('='))
.Where(a => a[0] == "OU")
.Select(a => a[1])
.Reverse().Skip(1).FirstOrDefault();
result is either null or has the string you want. This will work no matter how many OUs are in there and return the second-to-last one, as long as the format of the string is valid to begin with.
Update: possible improvements:
The above will not work correctly if your DN contains an escaped forward slash or an escaped comma.
To fix both of these you need to use regular expressions. Change:
str.Substring(str.LastIndexOf('/') + 1).Split(',')
to:
Regex.Split(Regex.Split(str, "(?<!\\\\)/").Last(), "(?<!\\\\),")
What this does is separate the DN by getting the last part of str after splitting on forward slashes, and split the in parts DN by splitting on commas. In both cases, negative lookbehind is used to make sure that the slashes/commas are not escaped.
Not as pretty, I know. But it's still an one-liner (yay!) and it still allows you to use LINQ further down to handle multiple OUs any way you choose to.

Categories