How do I query across child and parent fields using a multimatch type query in ElasticSearch? - elasticsearch

Example:
Parent doc
id: 1
field1: politics
field2: donkeys
Child doc
parent_id: 1
field1: prose
I would like to be able to search for the words 'politics donkey prose' (as an AND query, but not caring which fields any of the words match) and have it match the parent document. Is this possible? Or do I need to start rolling up the children as a big field within the parent (very undesirable because there can be many children)?
I am preferably looking for the solution in Java, but I will take it any way I can get it!

I think this might do it:
String parent_fields = "f1,f2";
String child_fields = "f3,f4";
BoolQueryBuilder allQueries = QueryBuilders.boolQuery();
for( String term : terms )
{
BoolQueryBuilder booly = QueryBuilders.boolQuery();
for( String field : parent_fields.split( "," ) )
{
booly.should( QueryBuilders.termQuery( field, term ) );
}
for( String field : child_fields.split( "," ) )
{
booly.should( QueryBuilders.topChildrenQuery( child_type, QueryBuilders.termQuery( field, term ) ) );
}
allBoolies.must( booly );
}

Related

How to properly escape parameters for JSONB deep query in node-postgres

When bypassing an ORM and doing direct queries to node-postgres, there are a nice pile of weird edge issues to keep in mind. For example, you have probably already encountered the fact that camelCaseColumns have to be in double-quotes, and also parameterized type casting…
client.query(`SELECT id, "authorFirstName", "authorLastName" FROM books WHERE isbn = $1::int`, [1444723448]`)
client.query(`SELECT id FROM books WHERE "authorLastName" = $1::string`, ['King']`)
JSON and JSONB types add another aspect of weirdness. The important thing to keep in mind is, "$1" is not merely a variable placeholder; it is an indicator of a discrete unit of information.
Given a table where characters is a column of type JSONB, this will not work…
client.query(
`SELECT id FROM books WHERE characters #> ([ {'name': $1::string} ])`,
['Roland Deschain']
)
This fails because the unit of information is the JSON object, not a string you're inserting into a blob of text.
This is a little more clear when one looks at a simpler SELECT and an UPDATE…
const userData = await client.query(
`SELECT characters FROM books WHERE id = $1::uuid`,
[ some_book_id ]
)
const newCharacters = JSON.stringify([
...userData[0].characters,
{ name: 'Jake' },
{ name: 'Eddie' },
{ name: 'Odetta' }
])
await this.databaseService.executeQuery(
`UPDATE books SET characters = $1::jsonb WHERE id = $2::uuid`,
[ newCharacters, some_book_id ]
)
The deep search query should be formed thusly:
const searchBundle = JSON.stringify([
{'name': 'Roland Deschain'}
])
client.query(
`SELECT id FROM books WHERE characters #> ($1::jsonb)`,
[searchBundle]
)

IN operator in Couchbase Lite

I need to query something like
SELECT * FROM `sample` WHERE id IN ["123", "456"]
This is converted into QueryBuilder as below
QueryBuilder
.select(SelectResult.all())
.from(DataSource.database("sample"))
.where(Expression.property("id")
.in([
Expression.string("123"),
Expression.string("456")
])
)
This doesn't work, and return empty list of result, any idea?
I see from your comments that your code worked (it was false negative). Yet I'll share an approach which may be useful in case you need to use the like operator against multiple wildcarded (%) expressions. Sample is in Kotlin language:
val list = listOf("123", "456")
val items = list.map { Meta.id.like(Expression.string("$it-%")) }.toMutableList()
val whereExpression = items
.fold(items.removeAt(0)) { chain, next -> chain.or(next) }
val query = QueryBuilder.select(
SelectResult.expression(Meta.id),
SelectResult.all()
).from(DataSource.database(this.db)).where(whereExpression)
val results = query.execute()
val resultList = results.allResults()

HQL Query - Part of String matches with part of String

As mentioned in subject, I am trying to match partial of one string with partial of other string.
I am using HQL for querying.
Eg. "mycar" should be matching with "carpool". Because "car" is there in "carpool".
query = "select j from Part p, Job j join p.partNumbers numbers where p.id = j.part.id and numbers LIKE CONCAT('%',:partNumber,'%') and p.forRepair = true";
jobs = entityManager.createQuery( query, Job.class )
.setParameter( "partNumber", searchValue )
.getResultList();
In above query, It works only in certain cases.
match : "2222" -----> "222222"
Doesn't match: "a22" ---> "2222222"
Any suggestion, or any useful resource I can find useful in this case?
Thanks for your help.

elastic search aggregation and filter in R

How do I create a bucket aggregation based on a field value, and then run a query that gives me hits for each bucket (and not each document) with filters?
New in elastic search and I will appreciate any help!
I'm working my way through this currently. So far, I've figured out how to aggregate on a field, but haven't been able to apply filters yet. Please let me know if you've made progress as I see this was posted a while ago...
# connect to elastic search
elastic::connect('connection_string',
es_port = 9200)
# define aggregation
aggs <- list(
aggs = list(
field_name = list(
terms = list(
field = "field_name"
)
)
)
)
# search
Search(index = 'index_name',
body = aggs,
asdf = T)
I managed to apply filter for date as follows:
last_week <- query('{
"range" : {
"your_date_field" : {
"gte" : "mondays-date",
"lt" : "sundays-date"
}
}
}')
I used this as the main query. I think you can apply the aggregating to this with the %search% (last_week + agg) notation and it should work.

LINQ Lamba Select all from table where field contains all elements in list

I need a Linq statement that will select all from a table where a field contains all elements in a list<String> while searching other fields for the entire string regardless of words.
It's basically just a inclusive word search on a field where all words need to be in the record and string search on other fields.
Ie I have a lookup screen that allows the user to search AccountID or Detail for the entire search string, or search clientID for words inclusive words, I'll expand this to the detail field if I can figure out the ClientId component.
The complexity is that the AccountId and Detail are being searched as well which Basically stops me from doing the foreach in the second example due to the "ors".
Example 1, this gives me an the following error when I do query.Count() afterwards:
query.Count(); 'query.Count()' threw an exception of type 'System.NotSupportedException' int {System.NotSupportedException}
+base {"Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator."} System.SystemException {System.NotSupportedException}
var StrList = searchStr.Split(' ').ToList();
query = query.Where(p => p.AccountID.Contains(searchStr) || StrList.All(x => p.clientID.Contains(x)) || p.Detail.Contains(searchStr));
Example 2, this gives me an any search word type result:
var StrList = searchStr.Split(' ').ToList();
foreach (var item in StrList)
query = query.Where(p => p.AccountID.Contains(searchStr) || p.clientID.Contains(item) || p.Detail.Contains(searchStr));
Update
I have a table with 3 fields, AccountID, ClientId, Details
Records
Id, AccountID, CLientId, Details
1, "123223", "bobo and co", "this client suxs"
2, "654355", "Jesses hair", "we like this client and stuff"
3, "456455", "Microsoft", "We love Mircosoft"
Search examples
searchStr = "232"
Returns Record 1;
searchStr = "bobo hair"
Returns no records
searchStr = "bobo and"
Returns Record 1
searchStr = "123 bobo and"
Returns returns nothing
The idea here is:
if the client enters a partial AccountId it returns stuff,
if the client wants to search for a ClientId they can type and cancel down clients by search terms, ie word list. due to the large number of clients the ClientID Will need to contain all words (in any order)
I know this seems strange but it's just a simple interface to find accounts in a powerful way.
I think there are 2 solutions to your problem.
One is to count the results in memory like this:
int count = query.ToList().Count();
The other one is to not use All in your query:
var query2 = query;
foreach (var item in StrList)
{
query2 = query2.Where(p => p.clientID.Contains(item));
}
var result = query2.Union(query.Where(p => p.AccountID.Contains(searchStr) || p.Detail.Contains(searchStr)));
The Union at the end acts like an OR between the 2 queries.

Resources