Elastic Search - Accessing a member of an element inside a list - elasticsearch

I'm relatively new to elastic search and have a question about accessing an element inside of an element inside of a list. The structure is as follows:
{
'TestA':'1',
'TestB':{
'TestC':'2',
'TestD':[
{
'TestE':'3',
'TestF':'4'
},
{
'TestE':'5',
'TestF':'6'
}
]
}
}
With this following structure I want to return all the results from the query in which TestF has a value of 6. I was wondering if this is possible with the following template.
{
"query":{
"bool":{
"must":[
{
"match":{
"TestB.TestD.TestF":'6'
}
}
]
}
}
}
Would {"match" : { "TestB.TestD.TestF": '6'}} be able to search through each element of 'TestD' or would I need to use some other command to iterate through the list? This is with elastic search 5.0. Thanks in advance!

Yes, your match query should find the results you are looking for. Elasticsearch flattens arrays when it puts them in the inverted index. For more information, check out the docs:
https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html#_how_arrays_of_objects_are_flattened
Arrays of inner object fields do not work the way you may expect.
Lucene has no concept of inner objects, so Elasticsearch flattens
object hierarchies into a simple list of field names and values.

Related

Filter nested array in graphQL

I am trying to filter an array of quotes based on what work or event the quote is referencing.
I only want the quotes referencing the current work the user is visiting. I've tried filtering, but I can't get it to work.
query MyQuery {
allSanityQuote {
edges {
node {
work {
... on SanityEvent {
_id
}
}
}
}
}
}
I want the _id in SanityEvent to match wphb0cG6N3lm4RQzm1xf51
Is SanityEvent a so called union? I've tried to read the graphQL documentation, but can't seem to find any example of this.

ElasticSearch - creating exceptions for fuzzy terms

I have simple elastic query that does a simple text field search with the fuziness distance of one:
GET /jobs/_search
{
"query": {
"fuzzy": {
"attributes.title": {
"value": "C#"
"fuzziness": 1
}
}
}
}
The above query does exactly what it is told to do, but I have a cases where I don't want a word to resolve (with fuzziness) to another specific word. In this case, I don't want C# to also return C++ results. Similarly I don't want cat to return car results.
However I do still need the fuzziness option if someone did actually misspelled cat. In that case it can return results of both cat and car.
I think this is possible with some bool query combination, it should be something like this:
bool:
//should
//match query without fuzzy
//bool
//must
//must with fuzzy query
//must_not with match query

Separate indices or use type field in Elasticsearch

I'm developing an Elasticsearch service and we have multiple sources like our support ticket portal and a forum. Currently, I'm segregating each source into it's own index as each will have a child type. The ticket portal will of course search tickets (with nested replies) but also search users and such so there are multiple types under the portal index. Simple stuff so far.
However, I'm starting to think of merging the indices and prefix the type (portalTicket, portalUser, forumThread, forumUser, etc) as I'm wanting to search across both sources, but maybe there is a way to query them and bring it all back together. I'm just working with tickets and threads at the moment to start small, here are the two simples mappings I'm using thus far:
{
ticket : {
properties : {
replies : {
type : 'nested'
}
}
}
}
{
thread : {
properties : {
posts : {
type : 'nested'
}
}
}
}
Wanted to show that to show I'm using nested objects with different names. I can of course have same names but there will also be other meta data attached to the ticket and thread mappings that will be nested types also and that takes me to the issue. When I search without specifying the index, I get issues with some not having the nested type, as expected. The thread mapping doesn't have a replies property, it's posts. I can get around it using index in a filter like so:
{
filter : {
indices : {
index : 'portal',
no_match_query : 'none',
query : {
bool : {
should : [
{
match : {
title : 'help'
}
},
{
nested : {
path : 'replies',
query : {
match : {
'replies.text' : 'help'
}
}
}
}
]
}
}
}
}
}
Ok, that works for the portal index but working it to include the forum index is making me feel like I'm just fighting elasticsearch and not using it properly.
So should I keep them on separate indices and get a filter that will return both indices results or should I merge them into a single index, use a field to hold the source and likely normalize the nested properties or is there a way to work with multiple indices in a faceted way? (I know, aggregates in ES 2)
Reading these two posts (thanks to the commenters for pointing these out):
Elastic search, multiple indexes vs one index and types for different data sets?
https://www.elastic.co/blog/index-vs-type
I have decided that my data is too different and the amount of documents that I anticipate (and future additions) means that I should go with different indices.
Now to learn how to search across the different indices but this post was more about which strategy I should use so I'm going to open a new question for that.

java: how to limit score results in mongo

I have this mongo query (java):
TextQuery.queryText(textCriteria).sortByScore().limit(configuration.getSearchResultSize())
which performs a text search and sort by score.
I gave different wiehgt to different fields in the docuemnt, and now I'd like to retrieve only those results with score lower then 10.
is there a way to add that criteria to the query?
this didn't work:
query.addCriteria(Criteria.where("score").lt(10));
if the only way is to use aggregation - I need a mongoTemplate example for that.
in other words
how the do I translate the following mongo shell aggregate command, to java spring's mongoTemplate command??
can't find anywhere how to use the aggregate's match() API with the $text search component (the $text is indexed on several different fields):
db.text.aggregate(
[
{ $match: { $text: { $search: "read" } } },
{ $project: { title: 1, score: { $meta: "textScore" } } },
{ $match: { score: { $lt: 10.0 } } }
]
)
Thanks!
Please check with below code sample, MongoDB search with pagination code in java
BasicDBObject query = new BasicDBObject()
query.put(column_name, new BasicDBObject("$regex", searchString).append("$options", "i"));
DBCursor cursor = dbCollection.find(query);
cursor.skip((pageNum-1)*limit);
cursor.limit(limit);
Write a loop and and call the above code from loop and pass the values like pageNum starts from 1 to n and limit depends on your requirement. check the cursor is empty or not. If empty skip the loop if not continue calling the above code base.
Hope this will be helpful.

how to sort the field in the mongo document which is inside array

I have below a structured Mongo Document:
{
"_id": value,
"imageShared": {
"imageid": value,
"commentdatadoc": [
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(111)
},
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(444)
},
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(222)
}
]
}
};
Here I want to sort the field commenttimestamp desc. I tried the way below but it is not working...
Query getComments = new Query();
getComments.addCriteria(Criteria.where("imageShared.imageId").is(imageId)).
with(new Sort(Sort.Direction.DESC,"imageShared.commentDataDoc"));
SharedMediaCollec sharedMediaCollec = mongoTemplate.findOne(getComments, SharedMediaCollec.class);
Does anyone have an idea how to sort a document field which is inside array?
When you need to get all documents anyway, it might be far easier to do the sorting in C# after you received the data from MongoDB. An elegant way to do this automatically would be to represent the commentdatadoc array in your C# object with a SortedSet.
But when you definitely want a database-sided solution, you can do it with an aggregation pipeline consisting of a $match-step, a $unwind step and a $sort step. To perform an aggregation with the C# driver, call collection.Aggregate and then set the aggregation stages at the returned IAggregateFluent interface.

Resources