Similar to elasticsearch match two fields,
I would like to execute a query in ES that uses OR operator
SELECT * FROM [mytype] WHERE title = 'some title' OR title = 'something else'
You can use bool/should clause
{
"query":{
"bool":{
"should":[
{
"match":{
"title":"some title"
}
},
{
"match":{
"title":"something else"
}
}
]
}
}
}
Related
I'm trying to get a MongoDB aggregate pipeline working. I need to match name to "John" and regex their "hometown" field to regex matching "CAPETOWN" or "FLORIDA" without case sensitivity. Basically if either of those patterns exist in the "hometown" field of the document. This is what I have so far.
const news = await cachedDb.collection(COLLECTION).aggregate([
{ $match: { "name": "John", "hometown": { $regex: /CAPETOWN/, $options: 'i' } } }
]).toArray();
I can only get CAPETOWN included, I want an OR. Such as "hometown" contains CAPETOWN OR FLORIDA with option (i). How do I go about doing that?
You have to set OR directly in the regex string.
db.collection.aggregate([
{
$match: {
"hometown": {
$regex: "CAPETOWN|FLORIDA",
$options: "i"
}
}
}
])
You can test it here
My team started to use MongoDB now and wanna migrate some sql to Mongo.
For example, I have an order table and has the fields price and quanty.I want to query the price*quanty greater than 100. sql is like below
select * from Order where price * quanty > 100;
How to use "price * quanty" this kind query in Mongo?
Thanks.
You can do this by using the $expr operator to use aggregation expressions within your query:
db.orders.find({
$expr: {
$gt: [
{ $multiply: ["$price", "$quantity"] },
100
]
}
})
As JohnnyHK points out you can use $expr, but as an alternative you can also use aggregation to first create a new field that is the product of two other fields:
db.orders.aggregate([
{ $set: { product: { $multiply: [ "$price", "$quantity" ] } } }
])
Note: $set is new in 4.2 and just an alias for $addFields
Then add a $match stage that only matches documents with the new product field meeting your condition:
db.orders.aggregate([
{ $set: { product: { $multiply: [ "$price", "$quantity" ] } } },
{ $match: { product: { $gt: 100 } } }
])
How can I convert the following SQL query to Java Elasticsearch Query?
SELECT s.*
FROM supplier_detail_info sdi
JOIN supplier s ON sdi.supplier_id = s.id
JOIN supplier_detail sd ON sdi.supplier_detail_id = sd.id
WHERE (sdi.value = '70' AND sd.id = 1 ) OR (sdi.value = '46' and sd.id = 4);
I have tried the following (excluding the OR clause from above) but failed:
def query = QueryBuilders.boolQuery().
must(QueryBuilders.nestedQuery('supplierDetailInfos', QueryBuilders.matchQuery("supplierDetailInfos.value", '46')))
.must(QueryBuilders.nestedQuery('supplierDetailInfos.supplierDetail', QueryBuilders.matchQuery("supplierDetailInfos.supplierDetail.id", 4)))
This resulted in:
{
"bool" : {
"must" : [ {
"nested" : {
"query" : {
"match" : {
"supplierDetailInfos.value" : {
"query" : "46",
"type" : "boolean"
}
}
},
"path" : "supplierDetailInfos"
}
}, {
"nested" : {
"query" : {
"match" : {
"supplierDetailInfos.supplierDetail.id" : {
"query" : 4,
"type" : "boolean"
}
}
},
"path" : "supplierDetailInfos.supplierDetail"
}
} ]
}
}
I'm using grails 2.3.7 and have the followings domains:
class Supplier {
String name
....
static hasMany = [supplierDetailInfos : SupplierDetailInfo]
static searchable = {
only = ['name', 'supplierDetailInfos']
supplierDetailInfos component: true
}
}
class SupplierDetailInfo {
SupplierDetail supplierDetail
Supplier supplier
String value
static searchable = {
only = ['id', 'supplierDetail', 'value']
supplierDetail component: true
}
}
class SupplierDetail {
String name
....
static searchable = {
only = ['id']
}
}
I'm using elasticsearch 2.3.5 and the elastic search plugin "org.grails.plugins:elasticsearch:0.1.0".
From what I understand,
must is equivalent to AND
&
should is equivalent to OR.
The above query should have returned only those suppliers for which the value of supplier_detail_info is '46' when the supplier_detail id is 4. But it returns all suppliers for whom there exists a supplier detail info with value '46'. It simply ignores the 'and sd.id = 4' part of the query. Also, I cannot figure out how to use the OR part.
Instead of a bool query try a nested query with a bool inner query and two must clauses. Also I think that the match queries should be term queries as they seem like keyword/long fields and not text fields and if you want OR make the must a should clause
{
"query":{
"nested":{
"path":"supplierDetailInfos",
"query":{
"bool":{
"must":[
{
"match":{
"supplierDetailInfos.value":"46"
}
},
{
"match":{
"supplierDetailInfos.supplierDetail.id":4
}
}
]
}
}
}
}
}
I found the solution to my problem thanks to #sramalingam24.
The elasticsearch query can be written as follows:
{
"query":{
"nested":{
"path":"supplierDetailInfos",
"query":{
"bool":{
"must":[
{
"match":{
"supplierDetailInfos.value":"46"
}
},
{
"query":{
"nested":{
"path":"supplierDetailInfos.supplierDetail",
"query":{
"bool":{
"must":[
{
"match":{
"supplierDetailInfos.supplierDetail.id":4
}
},
]
}
}
}
}
}
]
}
}
}
}
}
The equivalent query can be written using QueryBuilders as follows:
def supplierDetailQuery = QueryBuilders.boolQuery()
def supplierDetailIdQuery = QueryBuilders.nestedQuery('supplierDetailInfos.supplierDetail',
QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("supplierDetailInfos.supplierDetail.id", id)))
def supplierDetailIdAndValueQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("supplierDetailInfos.value", value))
.must(supplierDetailIdQuery)
supplierDetailQuery.must(QueryBuilders.nestedQuery('supplierDetailInfos',
supplierDetailIdAndValueQuery))
there is documents with category(number), and piece(long) fields. I need some kind of aggregration that group these docs by category and sum all the pieces in it
here how documents looks:
{
"category":"1",
"piece":"10.000"
},
{
"category":"2",
"piece":"15.000"
} ,
{
"category":"2",
"piece":"10.000"
},
{
"category":"3",
"piece":"5.000"
}
...
The query result must be like:
{
"category":"1",
"total_amount":"10.000"
}
{
"category":"2",
"total_amount":"25.000"
}
{
"category":"3",
"total_amount":"5.000"
}
..
any advice ?
You want to do a terms aggregation on the categories, from the records above I see that you are sending them as strings, so they will be categorical variables. Then, as a metric, pass on the sum.
This is how it might look:
"aggs" : {
"categories" : {
"terms" : {
"field" : "category"
},
"aggs" : {
"sum_category" : {
"sum": { "field": "piece" }
}
}
}
}
I am issuing a query to elasticsearch and I am getting multiple record types. How do I limit the results to one type?
The following query will limit results to records with the type "your_type":
curl - XGET 'http://localhost:9200/_all/your_type/_search?q=your_query'
See http://www.elasticsearch.org/guide/reference/api/search/indices-types.html for more details.
You can also use query dsl to filter out results for specific type like this:
$ curl -XGET 'http://localhost:9200/_search' -d '{
"query": {
"filtered" : {
"filter" : {
"type" : { "value" : "my_type" }
}
}
}
}
'
Update for version 6.1:
Type filter is now replaced by Type Query: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-type-query.html
You can use that in both Query and Filter contexts.
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"must" :[{"term":{"_type":"UserAudit"}}, {"term" : {"eventType": "REGISTRATION"}}]
}
}
}
},
"aggs":{
"monthly":{
"date_histogram":{
"field":"timestamp",
"interval":"1y"
},
"aggs":{
"existing_visitor":{
"terms":{
"field":"existingGuest"
}
}
}
}
}
}
"_type":"UserAudit" condition will look the records only specific to type
On version 2.3 you can query _type field like:
{
"query": {
"terms": {
"_type": [ "type_1", "type_2" ]
}
}
}
Or if you want to exclude a type:
{
"query": {
"bool" : {
"must_not" : {
"term" : {
"_type" : "Hassan"
}
}
}
}
}