I started using NEST and got it working. I see that the query as string is depricated. Is there another way of doing this? lets say I want to search for "test" in the whole index.
Passing as string is indeed deprecated but will not be removed.
To search for a term over all indices use:
this.ConnectedClient.Search<MyDTO>(s=>s
.AllIndices()
.Query(q=>q.Term(f=>f.Name, ""))
);
Make sure to look at the test project and the documentation which have alot of example code.
You can just use the querystring query type if all you are looking for is to search by a single word across all fields for a document type.
Client.Search<T>(q=>q.Index("MyIndex").Query(q=>q.QueryString("test")))
Related
My database is postgress and I allready have it scaffolded and properly mapped to MVCs. Now I have encountered a problem, because now I need a way to call full-text search, like in this simple query
Select * from fl_file storage where fl_file.text ## 'dog cat rain';
I haven't found a way how to write a LINQ query that will be translated in above sql string, except making some LINQ extension method that would call to stored procedure which would just execute full text search.
I find this approach "a bit" clumsy, and I'm pretty shure that if I'll do it, I'll just reinvent a wheel (probably square one) so any help with solving this problem would be apreciated
I found way to do this, though I firstly didn't know how to combine LINQ with pure SQL. In .net core its FromSql in Microsoft.EntityFrameworkCore.Relational assembly
String str = "dog cat rain";
_context.FlFile.FromSql(#"select * from fl_file where fts ## plainto_tsquery({0})", str)
I am trying to build a search function for a REST API using mongodb and C#.
I am trying to use the $in mongodb filter in a query. I know that hard coding the filter string {\"name\":{$in:[/^First/]}} find the record as I wish to, however I cannot get the same functionality when using Filter.In.
In my mongo repo I have a GetAsync that takes in the name and does the following:
return await Context
.Collection<TChronosDocument>()
.Find(
//"{\"name\":{$in:[/^First/]}}")
Builders<TChronosDocument>.Filter.In(x => name, ToRegex(name)))
.Sort(SortDefinition)
.Page(offset, limit)
.ToListAsync()
.ToAggregate(Mapper);
The ToRegex function merely converts a string like First into a string[] like [/^First/] for use by the filter.
The problem here is that this returns an empty array for the results instead of correctly matching to the entry with name : "First Agency".
I'm not sure if this is the correct way to go about achieving the $in functionality in C#, or if I am just doing something else wrong here.
(PS: I have tried using Find(Builders<TChronosDocument>.Filter.In(name, ToRegex(name))) with no luck either).
Try replacing
Builders<TChronosDocument>.Filter.In(x => name, ToRegex(name)))
with
Builders<TChronosDocument>.Filter.ElemMatch(x => name, ToRegex(name))
I have a list of strings that are search Queries.
I want to see if a string from the database contains anyone of those terms in the Query. I'd like to do this on one line of code, that doesn't make multiple calls to the database. This should work but I want it to be more optimized.
var queries = searchQuery.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries).Distinct();
var query = context.ReadContext.Divisions.AsQueryable();
queries.ForEach(q => {
query = query.Where(d => (d.Company.CompanyCode + "-" + d.Code).Contains(q));
});
Is there a function that can do this better or a more optimal way of writing that?
There are two issues with your proposed solution:
Most LINQ to SQL providers don't understand string.Contains("xyz") so the provider will either throw an exception or fetch all the data to your machine. The right thing to do is to use SqlMethods.Like as explained in Using contains() in LINQ to SQL
Also, the code you show will check whether the division contains all of the specified strings.
To implement the 'any' behavior you need to construct a custom expression, which will not be possible using plain C#. You would need to look at the System.Linq.Expressions namespace: https://msdn.microsoft.com/en-us/library/system.linq.expressions(v=vs.110).aspx
It is possible, but quite involved.
I have done Fuzzy search in lucene.Net. In this if i searched Feature, the Feature,Featured,featuring only should come.But the data came like based on text matching like venture,culture and etc. ture is matched in that fuzzy search.My code is
Query query = new FuzzyQuery(new Term("ContentText", searchString));
finalQuery.Add(query, BooleanClause.Occur.SHOULD);
You should take a look on the process called "Lemmatisation" (http://en.wikipedia.org/wiki/Lemmatisation). You would like to build your index based on the base form of the word (called lemma) - and the same you should do with your query.
Lucene supports English language out of the box so there should not be any problem with that.
You can pass additional filters that check the minimumscore property as well as the minimumsimilarity property that can enhance the quality of the results. Other things I have done in specific scenarios is use multiple different query types and combine the results (filter out low scores) and return a combined list. This works really well for things like an engine that can dynamically "assume did you mean..." results initially rather than asking you "did you mean".
You probably need to set Parser.FuzzyMinSim
So, in my last post I was asking how to build a dynamic search filter using LINQ and EF4 (See Here) and finally came up with the solution of building the expression as a string and parse it to an expression using the Dynamic LINQ library.
I that solved the problem. I was able to generate a Expression<Func<TSource, out bool>> and pass it to the Where() method of the DbSet. I am also trying to do this using MySql as a database behind EF4.
The problem came when I tried to apply string operations to integers, like searching a database record which consecutive number starts with 1234.
My initial expression was something like: record.ConsecutiveNumber.ToString().StartsWith("1234"). Sadly, as expected, things were not that easy as EF4 fails to query the DbSet with exception:
"LINQ to Entities does not recognize
the method 'System.String ToString()'
method, and this method cannot be
translated into a store expression."
After some Google search I found that this is a common problem. But C'MON! Is there a way to perform a search function that can search records with a consecutive number starting by "1234"?
How pros implement search features with EF4? This is with a single property filter. What if I wanna add multiple filters? God, my head hurts... :/
Thanks!
EDIT:
Thought #1: What about a stored procedure? What about calling a MySql stored procedure from Linq? Am I aiming way too high?
You can use the SqlFunctions.StringConvert method. It requires a double (or decimal) so you'll have to cast your int ConsecutiveNumber.
Replace:
record.ConsecutiveNumber.ToString().StartsWith("1234")
With:
SqlFunctions.StringConvert((double)record.ConsecutiveNumber).StartsWith("1234")
Have you looked at the Dynamic LinQ Library:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
And for your question
How to use "contains" or "like" in a dynamic linq query?
Previously I have gotten the code for this lib and just taken a look inside, it is pretty easy to follow.
This would be my thought process on getting it to work. Hopefully it points you in the right direction.
According to other posts SqlFunctions.StringConvert((double)record.ConsecutiveNumber) works for Sql Server.
Problem with converting int to string in Linq to entities
And here is relevant information on linq conversions.
Linq int to string
And here is an answer hinting at writing your own sql function for stringconvert
Using a SQL Function in Entity Framework Select
If SqlFunctions.StringConvert doesn't work for you I'd suggest looking at figuring out how to do it in Sql and then writing your own [EdmFunction()] attribute based method.
I haven't got a clue if this will work over Linq to EF or not but presuming that they mapped the Math operations, this might solve your need:
record.ConsecutiveNumber / Math.Pow(10, Math.Truncate(Math.Log10(record.ConsecutiveNumber) - 3)) == 1234
This is basically dividing the number by a power of 10 just big enough to leave the first 4 digits.
I know this is very hacky and inefficient even if it works, but there you go. :)
Any method calls in a LINQ to Entities query that are not explicitly mapped to a canonical function will result in a runtime NotSupportedException exception being thrown.
Check mapping canonical function here:
http://msdn.microsoft.com/en-us/library/bb738681.aspx
In this case, you can use Math function. (I don't think code first can use in product project at that time)