I have an sql table with columns Name, Category, Location. I am using Elastic Search with NEST. my query like this:
var result = client.Search<Models.Search.Poll>(s => s.Query(q => q.Fuzzy(f => f.OnField(p => p.Name).Value(query))))));
So if there is a record with name = "We are here" and user search "are" , it returns result.
Now I need to add two more parameters category and location to this query:
so I made it like this:
var result = client.Search<Models.Search.Poll>(s => s.Query(q => q.Fuzzy(f => f.OnField(p => p.Name).Value(query).OnField(r => r.Category).Value(category))));
but it is not working with query field now. but it works with category now. here is what I get when I type name but dont select category:
StatusCode: OK,
Method: POST,
Url: http://server.abc.com:9200/pollit-dev/polls/_search,
Request: {
"query": {
"fuzzy": {
"category": {
"value": "Select a Category"
}
}
}
},
Response: {"took":2892,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}
I tried this one well:
var result = client.Search<Models.Search.Poll>(s => s.MatchAll().Query(q => q.Term(p => p.Name, query) || q.Term(p => p.Category,category) || q.Term(p => p.Location, Location)
but no luck so far.
Regards,
Asif Hameed
You have multiple options for that.
First one is almost like yours but you have to use a Bool condition there.
var result = client.Search<Models.Search.Poll>(s => s
.MatchAll()
.Query(q => q
.Bool(b => b
.Must(m => m.Term(p => p.Name, query) || m.Term(p => p.Category,category) || m.Term(p => p.Location, Location))
)
)
);
Now another option is to use queryContainers. Something like this:
var result = _Instance.Search<Models.Search.Poll>(q => q
.Query(qq =>
{
QueryContainer termQuery = null;
QueryContainer locationQuery = null;
QueryContainer categoryQuery = null;
termQuery = qq.Term(p => p.Name, query);
categoryQuery = qq.Term(p => p.Category,category);
locationQuery = qq.Term(p => p.Location, Location);
return termQuery || categoryQuery || locationQuery;
})
);
You can also elaborate the QueryContainers and add multiple search parameters there.
Hope this helps you. Great day!
Related
I am using latest c# elastic search NEST library.
I am trying to search with exact text match, but currently it is working searching
for subset match. I want to do exact match.
Following is my code snippet:
public User GetUserByUsername(string username)
{
var client = new ElasticConnectionManager(this.configuration).GetClient(Constant.IndexUsers);
var searchResponse = client.Search<User>(s => s
.Query(q => q
.Bool(bq => bq
.Filter(f => f.Term(t => t.Username, username))
.Must(mt=>mt.Term(t2=> t2.Username, username)))));
//.Must(bs => bs.Term(t => t.Username, username))
if (searchResponse.Documents.Count > 0)
return searchResponse.Documents.First();
else
return null;
}
}
Try using the match_phrase query for exact text match. Your query should be similar to the following:
var searchResponse = client.Search<User>(s => s
.Query(q => q
.MatchPhrase(m => m
.Field(f => f.Username)
.Query(username))));
I have a line like so:
var lstOfIds = db.TBL_AssocIncidentSpecialCat
.Where(x => x.IncidentId == incidentVm.ID)
.Select(t => t.SpecialCategoriesId)
.ToList();
This line gathers me a list of of the SpecialCategoriesIds. Then I have to do this:
incidentVm.LstSpecialCategories = db.TBL_SpecialCategories
.Where(x => lstOfIds.Contains(x.Id))
.Select(t => t.SpecialCategory)
.ToList();
Is there a way to combine these two lines into one? Even though it's only two lines of code.. I feel as though having to grab the Ids first then having to grab the associated property based on the Id is just an extra step and could be shortened to just one line. But I may be wrong.
Any help is appreciated.
UPDATE
incidentVm.LstSpecialCategories = db.TBL_AssocIncidentSpecialCat
.Where(x => x.IncidentId == incidentVm.ID)
.Join(
db.TBL_SpecialCategories,
x => new{Id = x.SpecialCategoriesId},
t => new{Id = t.Id},
(x,t) => {return t.SpecialCategory}
);
I am getting red squiggly under last part in Join:
A lambda expression with a statement body cannot be converted to an expression tree
You can combine the two lines using Join. Something like,
var result = db.TBL_AssocIncidentSpecialCat
.Join(
db.TBL_SpecialCategories,
ais => new { Id = ais.IncidentId },
sc => new { Id = sc.Id },
(ais, sc) => { return sc; }
)
.ToList();
C# Fiddle for this.
Update with Where Clause: You should use your Where condition after the Join.
var result = db.TBL_AssocIncidentSpecialCat
.Join(
db.TBL_SpecialCategories,
ais => new { Id = ais.IncidentId },
sc => new { Id = sc.Id },
(ais, sc) => new { ais = ais, sc = sc }
)
.Where(x => x.ais.IncidentId == 1)
.Select(y => y.sc)
.ToList();
You can try a LINQ query-style join:
incidentVm.LstSpecialCategories = (from aispc in db.TBL_AssocIncidentSpecialCat
join spc in db.TBL_SpecialCategories
on aispc.SpecialCategoriesId equals lspc.Id
where aispc.IncidentId == incidentVm.ID
select lspc.SpecialCategory).ToList();
I was able to figure this out with the help of some answers and me testing it on my own. Here is my solution:
incidentVm.LstSpecialCategories = db.TBL_AssocIncidentSpecialCat
.Where(t => t.IncidentId == incidentVm.ID)
.Join(db.TBL_SpecialCategories,
ik => ik.SpecialCategoriesId,
ok => ok.Id,
(ik, ok) => ok.SpecialCategory
)
.ToList();
Thank you for all of your help.
I'm trying to select multiple columns not in a group by using linq - c#.
Using linq, I'm trying to group by ISNULL(fieldOne,''),ISNULL(fieldTo,'') and then select field_One, field_Two, field_Three for each group. So for each row that the group by would return, I want to see numerous rows.
So far I have the following, but can't seem to select all the needed columns.
var xy = tableQueryable.Where(
!string.IsNullOrEmpty(cust.field_One)
|| ! string.IsNullOrEmpty(ust.field_Two)
).GroupBy(cust=> new { field_One= cust.field_One ?? string.Empty, field_Tow = cust.field_Two ?? string.Empty}).Where(g=>g.Count()>1).AsQueryable();
Can somebody help pls?
You are pretty much there - all you are missing is a Select from the group:
var xy = tableQueryable
.Where(!string.IsNullOrEmpty(cust.first_name) || ! string.IsNullOrEmpty(ust.lastName))
.GroupBy(cust=> new { first_name = cust.first_name ?? string.Empty, last_name = cust.last_name ?? string.Empty})
.Where(g=>g.Count()>1)
.ToList() // Try to work around the cross-apply issue
.SelectMany(g => g.Select(cust => new {
Id = cust.Id
, cust.FirstName
, cust.LastName
, cust.RepId
}));
Select from each group does the projection of the fields that you want, while SelectMany dumps all the results into a flat list.
Would this work for you?
var groupsWithDuplicates = tableQueryable
.Where(c => !string.IsNullOrWhiteSpace(c.first_name) || !string.IsNullOrWhiteSpace(c.last_name))
.GroupBy(c => new { FirstName = c.first_name ?? "", LastName = c.last_name ?? "" })
.Where(group => group.Count() > 1) // Only keep groups with more than one item
.ToList();
var duplicates = groupsWithDuplicates
.SelectMany(g => g) // Flatten out groups into a single collection
.Select(c => new { c.first_name, c.last_name, c.customer_rep_id });
For me I have used following query to do the filter Customer and get the customer records group by the JobFunction. In my case the issue get resolved after adding the .AsEnumerable() after the where solve the problem.
var query = _context.Customer
.Where(x => x.JobTitle.ToUpper().Contains(searchText.ToUpper())).AsEnumerable()
.GroupBy(item => item.JobFunction,
(key, group) => new {
JobFunction = key,
CustomerRecords = group.ToList().Select(c => c).ToList()
})
.ToList();
I would like to order a Listview based on the products'name it displays. My website is made of several languages and thus I built a linked table with a product name for each languages.
When I try to sort it I always get this error
DbSortClause expressions must have a type that is order comparable.
Parameter name: key
My code is the following:
IQueryable<Product> query = from p in _dbCtx.Products
where p.LanguageProduct.Any(lg => lg.Language == _currentCulture)
select p;
...
if (keys.Contains("OrderBy"))
{
if (Request.QueryString["OrderBy"] == "NameAsc")
query = query.OrderBy(t => t.LanguageProduct.Select(v => v.ProductName));
}
Any suggestions? Many thanks in advance.
EDIT: Maybe I haven't been clear enough. Therefore, I'll add some more code:
IQueryable<Product> query = from p in _dbCtx.Products
where p.IsVisible == true
where p.LanguageProduct.Any(lg => lg.Language == _currentCulture)
select p;
if (keys.Contains("Indiv"))
{
if (Request.QueryString["Indiv"] == "IndivYes")
query = query.Where(c => c.IsCustomizable == true);
if (Request.QueryString["Indiv"] == "IndivNo")
query = query.Where(c => c.IsCustomizable == false);
}
if (keys.Contains("OrderBy"))
{
if (Request.QueryString["OrderBy"] == "NameAsc")
query = query.OrderBy(t => t.LanguageProduct.Select(v => v.ProductName));
else if (Request.QueryString["OrderBy"] == "NameDes")
query = query.OrderByDescending(t => t.LanguageProduct.Select(v => v.ProductName));
else if (Request.QueryString["OrderBy"] == "PriceAsc")
query = query.OrderBy(t => t.ListPrice);
else if (Request.QueryString["OrderBy"] == "PriceDes")
query = query.OrderByDescending(t => t.ListPrice);
}
Everything works fine by adding successive where clauses to my query until it has to order by name. Hereunder is the structure of my database:
table: Product ProductTranslation
columns: id ReferenceName FKId Language ProductName
Example: 1 FirstProduct 1 fr-FR Produit 1
1 de-DE Produkt 1
1 en-US Product 1
You can do this using this:
var queryable = query.SelectMany(p => p.LanguageProduct, (p, l) => new{p,l})
.OrderBy(t => t.l.ProductName)
.Select(t => t.p);
Below are the linq query. Here I want to add one condition .
Condition : If : Firstname is not empty then select list
where (d=>d.firstname=="Firstname")
else: select all list without condition
function Ponits(string Firstname)
{
pointsCore.Categories.SelectMany(c => c.Events).Select(e => new
{
e.Firstname,
e.Surname,
e.EntityNumber,
e.Eventdate
}).ToList()
}
Two options:
First, optionally use Where:
var events = pointsCore.Categories.SelectMany(c => c.Events);
if (!string.IsNullOrEmpty(firstName))
{
events = events.Where(e => e.Firstname == firstName);
}
var result = events.Select(e => new { ... });
Second: make your Where clause check firstName:
var events = pointsCore.Categories.SelectMany(c => c.Events);
.Where(e => string.IsNullOrEmpty(firstName) ||
e.Firstname == firstName)
.Select(e => new { ... });
Note that due to the lazy evaluation in LINQ, the first option won't involve fetching all the values and then querying; you're still just building up a query.
.Where(d => string.IsNullOrEmpty(Firstname) || d.firstname==Firstname)