Search query using first, middle and last name - search

I have a grails domain named Person, in that i have properties: firstName, middleName, lastName and others. I do not have a fullName field in the database, its a transients property in my domain. Now I want to create a search mechanism using all those three. Is there any way to implement this?
-> Update
I thought about this from different perspective and then it hit me !
So i did this,
My query
searchResult = Person.findAll("from Person p where p.firstName LIKE '%" + searchString + "%' or p.middleName LIKE '%" + searchString + "%' or p.lastName LIKE '%" + searchString + "%'")
but when i displayed the result, i limited the number of results, so the user has to enter more specific search string to get desired result. I also added a button "See More" so if the user can see all the fetched results but by default, it would only show a limited number of results.
(I could not answer to my own question so i wrote this in the question itself :D)

As long as there is a getter method I believe the Searchable plugin will work on transients.
public String getFullName()...

you need to pass params to fetch data in limited numbers.
i.e. .findAll(Query,params)

Related

how to increase azure searching performance

I am new to Azure services. In my project
there is a function to search text words or multiple text words. For example, if I search "best phase", the search should return data that are related "best" and "phase" in my data.
Sample example code below. Note: searchParameters is used to sort and order my data by their date
string searchText = "best phase";
string[] temp = searchText.Contains(" ") ? searchText.Split(' ') : new string[] { searchText};
var documentSearch = _indexClient.Documents.Search("\"" + searchText + "\"^2, \"|" + searchText + "|\", +" + searchText + ", +" + string.Join(", +", temp) , searchParameters);
The current implementation consumes too much time at around 15-20 sec or more. So I need to do searches faster. Any idea how to make it faster :-)
You can use Azure Search as explained here.
You can also use Full-Text Search of SQL Azure as explained here.
To decide which one to use, please read the difference between them on this article.
Hope this helps.

Query use for search in the view

I have a xpages booking application, there is a view for search officer's booking record. Due to search values may contains "(" or ")" or other symbols so I would use wild card search in the code. Also I need to ensure the search result returns properly so I created extra fields to connect two fields together (e.g. Fieldname1+++Fieldname2). I put the search code in view (In Properties -> Data -> Search in view results)
Here is the code for the search
var qstring= "";
if (
(sessionScope.officerSearch != null && sessionScope.officerSearch != "")||
(sessionScope.startDateSearch != null && sessionScope.startDateSearch != "")||
(sessionScope.returnDateSearch != null && sessionScope.returnDateSearch !=""))
{
qstring = " ( FIELD location+++group contains " + sessionScope.locationSearch +"+++"+ sessionScope.groupSearch +
" | FIELD location+++officer contains " + sessionScope.locationSearch +"+++"+ sessionScope.officerSearch +")" +
" & FIELD dateYYYYMM >=" + sessionScope.startDateSearch +
"& FIELD dateYYYYMM <=" + sessionScope.returnDateSearch;
}
return qstring;
When I run the application, I have two problems. If I search only one officer, I get an exception (Notes error: Query is not understandable). If I search more than one officer, I don't get the exception but the result does not return anything. So I use a computed field, paste the search code in there and run the program again. The computed field shows what I searched.
Due to I put the code in the computed field, I can read the whole query for the search
Problem 1: If I search one officer, although it occurs exception, I can imagine the query is like this
( FIELD location+++group contains "WEST+++GP AM(OSO)" | FIELD location+++officer contains "WEST+++John Freeman") & FIELD CompYMNUM >=201001& FIELD dateYYYYMM <=201712
If I put this query in Lotus Notes Client, and cick Search button, it returns the result properly
Problem 2: If I search multiple officers, although the result does not return anything, the computed field shows the query like this
( FIELD location+++group contains "WEST+++GP AM(OSO)" | FIELD location+++officer contains "WEST+++John Freeman, Kevin Sims, Sally Johnson, Tom Chan, William Ross") & FIELD dateYYYYMM >=201001& FIELD dateYYYYMM <=201712
I put this query in Lotus Notes Client, and cick Search button, it returns the result properly too.
I feel so strange that the Lotus Notes Client can return the proper result but the xpages cannot. Also I don't understand why if I search one officer, it causes exception (Query not understandable) and if I search more than one officer, it does not exception and not result return.
I think the reason I get the exception or the review does not the the result is I have "(" and ")" in the search value? However, I used wild card search to bound the search criteria (Or I misunderstand the wild card search?)
Also another reason I think is the field location+++officer. If search multiple officers, the field only recognize one officer e.g. "WEST+++John Freeman, Kevin Sims, Sally Johnson, Tom Chan, William Ross"?
Last but not least, maybe there is coding mistake in the code? But there is mistake in the code, I guess Lotus Notes Client will not return the result.
I try to solve the problems, but every time when I run the application, those problems still occurs.
Is my query has mistake?
Grateful if someone let me know my mistakes please? Thank you.

Grails search mechanism

For my website, i need to do a search mechanism, in which some of the entry field would be: Country, City, Between Dates (with or without year field), Keywords, etc etc.
My problem is, the user must decide what they wanna search for. For example, if they want to introduce just date, or date and city, or city and keyword.. etc. I dont really know how to do that, i mean, i know how to search for one thing at a time, but i'm not sure how can do this all-in-one.
a) Would i need like something like this: (if-else, if-else) and than write the code for each combination, or there is an easier way to do that?
b )Bytheway, my search mechanism is done the folowing way (i'v never done a search mechanism before, so i dont know if it is the best aproach, would apreciate some comments here also and suggestions):
class book{
String a
String b
...
Date z
String allAttributesTogether() {
a + b + c + ... + z
}
}
then in my controller, i do a double for statment and cross-match the introduced words for the search and the result of allAttributesTogether().
Thanks in advanced, VA
Check out the filter pane plugin.
When you say "search", comes to my mind search engines. But I think you are asking about querying the database, right?
If you are talking about search mechanisms, search engines are a great tool. You can take a look at Lucene, Compass, and ElasticSearch (ES) to name a few. Compass and ES are based on lucene, but are much higher in the abstraction level (easier to use).
I have been using ElasticSearch with great satisfaction.
If you are talking about querying the database, then you can just build a HQL query dynamically. The method bellow should be in a Controller, as it uses the params attribute. It is not tested ok?
List allAttributesTogether() {
def query = " select book from Book book "
def queryParams = [:]
def needsAnd = false
if(params.a || params.b || params.z ){
query += " where "
}
if(params.a){
query += " book.a = :a "
queryParams['a'] = params.a
needsAnd = true
}
if(params.b){
if(needsAnd) query += " and "
query += " book.b = :b "
queryParams['b'] = params.b
needsAnd = true
}
if(params.a){
if(needsAnd) query += " and "
query += " book.z = :z "
queryParams['z'] = params.z
}
return Book.executeQuery(query, queryParams)
}
There is also the alternative of using Criteria builder. You can also use "if" to add clauses to your Criteria clauses.

linq to entity Contains() and nested queries

i've a trouble with linq, i'll explain on example :
i have a database table called Employee which got FirstName and LastName columns,
and a method to search employees which gets a nameList list as argument, the elements in this list are names formatted like this one "Fred Burn", or this1 "Grim Reaper",
already tryed these approaches with no luck =[
//just all employees
var allData = from emp in Context.Employee select emp;
var test1 = from emp in allData
where(emp.FirstName + " " + emp.LastName).Contains
("" + ((from n in nameList select n).FirstOrDefault()))
select emp;
var test2 = (from emp in allData
where (emp.FirstName + " " + emp.LastName)
== ((from n in nameList select n).FirstOrDefault())
select emp);
var test3 = from emp in allData
where (from n in nameList select n).Contains
(emp.FirstName + " " + emp.LastName)
select emp;
first and second queries give : {"Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."} exceptionand third : {"LINQ to Entities does not recognize the method 'Boolean Contains[String](System.Collections.Generic.IEnumerable`1[System.String], System.String)' method, and this method cannot be translated into a store expression."}
would be glad to hear your suggestions :)
Thank You!
p.s.
yea i know it's possible to split names in list and compare them separately, but still curious why wont these queries work.
I assume nameList in this case is an in memory collection and that you are trying to use the LINQ to SQL trick creating a SQL "IN" clause inside of the Entity Framework. Unfortunately, EF doesn't support this syntax (yet). Depending on the number of records you are trying to match, you may be able to run separate queries for each child you are desiring. Alternatively, you could build an entitysql query using concatenation to append the multiple items from the nameList as separate OR clauses in the WHERE operation.

Calling an SQL function from a Subsonic.Select

I asked the following question on the subsonic forum, but only seemed to get one response, so I thought I'd post up here as well to see if anyone could shed some more light on the problem...
I wish to create the following SQL statement through SubSonic using the Select tool (or Query tool) .. it uses a custom function called "SPLIT()":
SELECT * FROM VwPropertyList
WHERE VwPropertyList.idCreatedBy = 123
AND VwPropertyList.idCounty = 45
AND 29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))
(the last part of this SQL uses the SPLIT function)
My subsonic equivalent looks like the following...
Dim mySelect As New SubSonic.Select
mySelect.From(VwPropertyList.Schema)
mySelect.Where(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
mySelect.And(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
mySelect.And(29).In(New SubSonic.Select("Item").From("SPLIT("
&
VwPropertyList.Columns.DistrictGroupList
& ", ',')"))
This doesn't work though due to the last part .. how can I add "AND 29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))" into my Subsonic.Select ?
The response I got from the subsonic forum suggested I do away with Subsonic.Select and replace with hard-coded InlineQuery() statements .. like:
Dim SQL as String = "Select " &
VwPropertyList.Columns.Item SQL = SQL
& " From " &
VwPropertyList.Schema.TableName SQL =
SQL & " Where " &
VwPropertyList.Columns.IdCreatedBy & "
= #CreatedBy " SQL = SQL & " And " & VwPropertyList.Columns.IdCounty & " =
#County " SQL = SQL & " And
#DistrictGroup IN (Select Item From
SPLIT(DistrictGroupList,',')"
Items =
SubSonic.InlineQuery().ExecuteTypedList(Of
MyItem)(SQL, 123,45,29)
I would prefer to use SubSonic.Select if possible though so that I can avail of the paging functionality etc.
Any ideas?
You could do John's suggestion or you could write the SQL using our InlineQuery - which allows you to write raw SQL and pass in params:
var qry=new InlineQuery("SELECT * FROM table WHERE column=#param",value)
You could try to use the original query object (pre 2.1) like so (untested, from memory):
Query q = new Query(VwPropertyList.Schema.TableName);
q.WHERE("29 IN (SELECT Item FROM SPLIT(DistrictGroupList, ','))");
// pass q.ExecuteReader() to the Load() method of your view.
I would suggest that you use the original Query object as you are looking to get paging. Inline Query does not have any methods that allow paging.
If you absolutely wanted to use Subsonic.Select you could mesh the two ideas and run an Inline Query to get the list of values and then use a Regular Subsonic.Select and pass the retrieved values to the select case but then you would be making two trips to the db.
On a side note I prefer reading Subsonic.Select statements written using the fluent interface that it is namely
SubSonic.Select.AllColumnsFrom()
.Where(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
.And(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
.ExecuteAsCollection();
thanks for the responses.
I ended up doing InlineQuery and just re-wrote the paging code that's normally produced by Subsonic.Select ... not the best solution but it seems to work.
It would be good if I could have done something like this though:
Dim s As New SubSonic.Select
s.From(VwPropertyList.Schema)
sWhere(VwPropertyList.Columns.IdCreatedBy).IsEqualTo(123)
sAnd(VwPropertyList.Columns.IdCounty).IsEqualTo(45)
s.And(29).In(New
InlineQuery("(SELECT Item FROM
SPLIT(DistrictGroupList, ','))"))

Resources