ElasticSearch query for items not in given array - ruby

I am trying to write a part of a query to filter out any items with a type as "group" and that have a group id that isn't in a given array of ids. I started writing a bool query with a must and must_not but I was getting tripped up on how to write "id not in the given array.
EDIT:
I am actually converting an outdated query using "and" and "not" to be ES 5.5 compatible. Here is the old query that worked.
:and => [
{
term: {
type: 'group'
}
},
{
:not => {
terms: {
group_id: group_ids
}
}
},
{
:not => {
terms: {
user_id: user_ids
}
}
}
]
group_ids and user_ids are arrays.

You probably have not analyzed the arrays with the IDs. You can use a Bool query with a filter clause, and then within that filter start a new bool query with a mustNot clause and within that clause add a terms query with your IDs.

bool: {
must: {
term: {
kind: 'group'
}
},
must_not: [
{
terms: {
group_id: group_ids
}
},
{
terms: {
user_id: user_ids
}
}
]
}

Related

What do I do when my query string in an elasticsearch is too long and the search doesn't work?

I'm querying Elastic in my GraphQL resolver like this below. The peopleArray under the second multi_match is dynamic and is filled with numbers (e.g. [101, 102, 103...]). This is for different users to get their messages. If the user's peopleArray has 165 items, it works fine. However, I have test users who have 1873 items in the peopleArray and the query doesn't work. And I may need to support users with 60,000 items. Basically, I'm creating a messaging system for employees in a company and all the numbers are all the people in their network of message-sending. If this is not a practical way of doing this, any suggestions would be appreciated. But if it is possible, how do I get my results? (Have not tried this in the Kibana UI yet.)
const esClient = new elasticsearch.Client({
host: config.elasticsearchRoot
});
const result = await esClient.search({
index: `${config.index.messageStream}`,
body: {
query: {
bool: {
must: [
{
multi_match: {
query: tenantId,
fields: [
"tenantId",
"discretionary.clientKey.systemTenantId",
"clientKey.systemTenantId",
"author.tenantId"
],
operator: "OR"
}
},
{
multi_match: {
query: peopleArray,
fields: ["author.peopleId", "details.recipient.peopleId"],
operator: "OR"
}
}
]
}
},
from,
size,
docvalue_fields: [
{
field: "sortDate",
format: "use_field_mapping"
}
],
sort: {
sortDate: {
missing: "_last",
unmapped_type: "long",
order: "desc"
}
}
}
});```

How to query from two elasticsearch indexes with one query

Newbie here. I have two indexes: /items and /categories that contain data similar to this:
#Items:
{ id:1, name: "banana", categories: [1] },
{ id:2, name: "coconut", categories: [1] },
{ id:3, name: "smoothie", categories: [1, 2] }
#Categories
{ id:1, name: "Apple" },
{ id:2, name: "Banana" }
I want to create a query with bana as a query string and I should return items 1 and 3. It should not return category objects. ID 1 because of the name match and ID 3 because it has a category that has a name match.
How could a query like this be constructed?
My current query does not return item 3 and simply like
GET /items/_search
{
"query": {
"bool":{
"must":{
"query_string":{
"query":"bana"
}
}
}
}
}
Is it necessary to create two indexes for this? maybe use name directly in Item index to replace id:
{ id:1, name: "banana", categories: ["Apple"] }
Since index will have its own dictionary, will not cause extra disk space.
if really need to join two indexes, maybe you want to try Parent-Child Relationship, but it will deprecated in future, and replaced by: join datatype, this way also will keep data in one index.

How to use ReQL filter and match command on arrays

I have a table in rethinkdb where each row has following structure -
{
'name':'clustername',
'services':[
{
'name':'service1'
},
{
'name':'service2'
}
]
}
I am running a query to filter service2 object like this
r.table('clusters').filter({"name": "clustername"})
.pluck('services').filter((service) => {
return service("name").match('service2')
})
But this is not returning anything: No results were returned for this query
Can anyone tell why this is happening?
pluck returns sequence, so this query:
r.table('clusters').filter({"name": "clustername"}).pluck('services')
will return:
{
"services": [
{
"name": "service1"
} ,
{
"name": "service2"
}
]
}
You need get services field from it, it will return array with services field of items found by filter.
And after that you need to use your second filter on each item by using map.
So, correct query:
r.table('clusters').filter({"name": "clustername"}).pluck('services')("services").map(item => {
return item.filter(service => {
return service("name").match("service2");
});
})

"OR" query in KeystoneJS Relationship Filters

Currently, all I see examples for is:
{
team: ':team'
}
But I need to be able to filter by multiple values ($or query)
Something like:
winner: {
type: Types.Relationship,
ref: 'Team',
filters: [
{
_id: ':homeTeam'
},
{
_id: ':awayTeam'
}
]
}
Is this possible?
Try the following code:
filters:{_id:{$in:[id_array]}}

Tire search return terms by first letter

I'm using Tire/ElasticSearch to create an alphabetical browse of all the tags in my database. However, the tire search returns the tag I want as well as all the other tags associated to the same item. So, for example, if my letter was "A" and an item had the tags 'aardvark' and 'biscuit', both 'aardvark' and 'biscuit' would show up as results for the 'A' query. How can I construct this so that I only get 'aardvark'?
def explore
#get alphabetical tire results with term and count only
my_letter = "A"
self.search_result = Tire.search index_name, 'tags' => 'count' do
query {string 'tags:' + my_letter + '*'}
facet 'tags' do
terms 'tags', :order => 'term'
end
end.results
end
Mapping:
{
items: {
item: {
properties: {
tags: {
type: "string",
index_name: "tag",
index: "not_analyzed",
omit_norms: true,
index_options: "docs"
},
}
}
}
}
Following things that you'll need to change:
Mapping
You need to map the tags properly in order to search through them. And as your tags, are inside you item document, you need to set the properties of tags as nested, so that you can apply your search query in the facets too. Here is the mapping that you need to set:
{
item: {
items: {
properties: {
tags: {
properties: {
type: "nested",
properties: {
value: {
type: "string",
analyzer: 'not_analyzed'
}
}
}
}
}
}
}
}
Query
Now, you can use prefix query to search through the tags that start with a certain letter and get the facets, Here is the complete query:
query: {
nested: {
path: "tags",
query: {
prefix: {
'tags.value' : 'A'
}
}
}
}
facets: {
words: {
terms: {field: 'tags.value'},
type: 'nested',
facet_filter: {prefix: {
'tags.value' : 'A'
}
}
}
}
Facet filter is applied while computing facets, so you'll only get the facets which will match your criteria. I preferred prefix query over regular exp. query because of performance issues. But I am not quite sure whether prefix query works for your problem. Let me know it it doesn't work.

Resources