facets in elastic 5.5 - database

I'm trying to build a feceted search with elastic 5.5 (With elastic 2.* I found information on how to do this but in 5.5 I can't)
Not something unusual, store-like items that i want to show hint of the amount if the user will choose to filter using some property. Image for visualisation
Data set example:
[
{
"id" : "978-0641723445",
"cat" : ["book","hardcover"],
"name" : "The Lightning Thief",
"author" : "Rick Riordan",
"series_t" : "Percy Jackson and the Olympians",
"sequence_i" : 1,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 12.50,
"pages_i" : 384
}
,
{
"id" : "978-1423103349",
"cat" : ["book","paperback"],
"name" : "The Sea of Monsters",
"author" : "Rick Riordan",
"series_t" : "Percy Jackson and the Olympians",
"sequence_i" : 2,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 6.49,
"pages_i" : 304
}
,
{
"id" : "978-1857995879",
"cat" : ["book","paperback"],
"name" : "Sophie's World : The Greek Philosophers",
"author" : "Jostein Gaarder",
"sequence_i" : 1,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 3.07,
"pages_i" : 64
}
,
{
"id" : "978-1933988177",
"cat" : ["book","paperback"],
"name" : "Lucene in Action, Second Edition",
"author" : "Michael McCandless",
"sequence_i" : 1,
"genre_s" : "IT",
"inStock" : true,
"price" : 30.50,
"pages_i" : 475
}
]
Thanks!

You just have to use aggs instead of facets. Aggregations are much more powerful than facets.
For example:
GET index/_search
{
"aggs" : {
"countries" : {
"terms" : { "field" : "country" }
},
"types" : {
"terms" : { "field" : "type" }
}
}
}
Then if a user click on a "facet", just add a filter clause within a bool query (this will update all facet counts) or add a post_filter to just filter the results (does not affect aggregations).

if the column is text, you will need to use ".keyword" too to handle cases of country names where there are many words ("El Salvador", "United States of America", etc)
GET index/_search
{
"aggs" : {
"countries" : {
"terms" : { "field" : "country.keyword" }
}
}
}

Related

MongoDB Transform element fields into array of values only

I need help with following thing in MongoDB, what I'm trying to do is to get only marks in reviews into it's own array of values only.
Code i got so far:
db.lodging.aggregate([
{$project:{
reviews:"$host.reviews",host:"$host"
}
},
{$unwind: "$reviews"},
])
JSON Example:
"host" : {
"name" : "Grimes",
"surname" : "Terrell",
"gender" : "male",
"age" : NumberInt(55),
"picture" : "https://api.adorable.io/avatars/285/GrimesTerrell.png",
"reviews" : [
{
"reviewer" : "Mae Ryan",
"date" : "2015-06-01T02:41:46 -02:00",
"helpful" : NumberInt(8),
"kind" : NumberInt(1),
"responsive" : NumberInt(5)
},
{
"reviewer" : "Nixon Johnson",
"date" : "2016-02-08T10:35:12 -01:00",
"helpful" : NumberInt(1),
"kind" : NumberInt(1),
"responsive" : NumberInt(9)
},
]
}
This is what im trying to achieve:
{
"host" : {
"name" : "Grimes",
"surname" : "Terrell",
"gender" : "male",
"age" : NumberInt(55),
"picture" : "https://api.adorable.io/avatars/285/GrimesTerrell.png",
"reviews" : [
{
"marks" : [8,1,5],
},
{
"marks" : [1,1,9],
},
]
}
Assuming your marks' field names are always helpful, kind, responsive, you can use $map.
Here is a mongo playground for you reference

Remove objects within array in MongoDB

I need to remove all the objects within array who meet the conditions i will show down below. I'll let here the documents and an example of what i've done.
//document 1
{
"_id" : ObjectId("5ec73abebd7e4d618a057350"),
"code" : "X20",
"title" : "Full stack developer",
"location" : "Paris",
"date" : ISODate("2020-05-22T02:36:46.272Z"),
"candidates" : [
{
"name" : "David",
"last_name" : "Broncano",
"telephone" : "642025552",
"email" : "david#gmail.com"
},
{
"name" : "Pablo",
"last_name" : "Claros",
"telephone" : "628721784",
"email" : "pablo#gmail.com"
}
]
}
// document 2
{
"_id" : ObjectId("4ec73abebd7e4d618a057350"),
"code" : "X50",
"title" : "Full stack developer",
"location" : "Madrid",
"date" : ISODate("2020-05-22T02:36:46.272Z"),
"candidates" : [
{
"name" : "Maria",
"last_name" : "Mars",
"telephone" : "642024582",
"email" : "dasd#gmail.com"
},
{
"name" : "Pablo",
"last_name" : "Claros",
"telephone" : "628721784",
"email" : "pablo#gmail.com"
}
]
}
So i need to remove all the candidates where location is Madrid.I have done this but it removes the field. Is it possible to just remove the content of it using $pull or something?
db.offers.update(
{ location : "Madrid"},
{
$unset:{
"candidates":""
} } ,
{
multi : true
}
)
According to my understanding, you need to just clear the candidates array and maintain that as candidates: []. For this, you can use use $set operator to set candidates to [] based on your condition
db.offers.update({ location : "Madrid"}, { $set:{ "candidates": [] } } , { multi : true })

Problems with JSON

I'm trying to Order in ascending order the requirements that are not between 25,000 and 30,000. The requirements are information of an array which is inside of a document and the condition is that they can't be in that determined range. I'm trying to do it properly but i can't find any information about this.
Document structure
{
"_id" : ObjectId("5ec73abebd7e4d618a05734e"),
"code" : "A47",
"title" : "Software engineer",
"description" : "Analyze, design, create, test computer and software systems.",
"city" : "Madrid",
"date" : ISODate("2020-05-22T02:36:46.271Z"),
"salary" : 30000.0,
"active" : true,
"requirements" : [
"python",
"java",
"html5",
"C++",
"C#"
],
"info_company" : {
"cif" : "A00000000",
"name" : "FUTURE S.A",
"location" : "Madrid",
"web" : "www.future.es",
"about" : "We are a leading company in new technologies."
},
"pyme" : true
}
db.offers.update(
{ $ne : [ salary: {
$gte : 25000,
$lte : 35000 ]
} },
{
$push : {
requirements: {
$each : [] ,
$sort : 1
}
}
}
,
{
multi : true
} )

MongoDB filter a single value against a array list

I am trying to figure out a way to filter a single value against an array in aggregation. For example i have below data:
{ "user" : "InternetBot", "userid" : 001, "timestamp" : "2020-02-22T00:51:07Z", "title" : "Australia" }
{ "user" : "ArchiveBot", "userid" : 031, "timestamp" : "2020-02-22T00:51:07Z", "title" : "Australia" }
{ "user" : "David", "userid" : 312, "timestamp" : "2020-02-22T00:51:07Z", "title" : "Another Book" }
{ "user" : "Tim", "userid" : 111, "timestamp" : "2020-02-22T00:51:07Z", "title" : "A novel" }
{ "user" : "AutoBot", "userid" : 222, "timestamp" : "2020-02-22T00:51:07Z", "title" : "A paint" }
I have a list recorded all the bot user, usch as:
[InternetBot, AutoBot, ArchiveBot ]
I wanted to filter user field against this list and only keep document whoes user is in this bot list, i.e output below:
{ "user" : "InternetBot", "userid" : 001, "timestamp" : "2020-02-22T00:51:07Z", "title" : "Australia" }
{ "user" : "ArchiveBot", "userid" : 031, "timestamp" : "2020-02-22T00:51:07Z", "title" : "Australia" }
{ "user" : "AutoBot", "userid" : 222, "timestamp" : "2020-02-22T00:51:07Z", "title" : "A paint" }
I also need to do this in Aggregation since I need to perform other stages as well.
I tried both $filter and $match but unable to make it work. This seems a stupid question but if anyone can help I will be appreciated!

Aggregate from one document array to another

I am trying to do a transformation from one data structure to another and am using NoSQL Booster as I feel more comfortable using SQL queries than I do using Mongo script, a little lazy but its worked for me thus far.
I have a document which has a an array of line items which represents a sales receipt. The line items are the items sold.
I have used the following SQL query to generate Mongo script to select and then rename values from one document to create another. Where I'm stuck is in selecting from an array some fields and renaming them into a new document within a new array.
mb.runSQLQuery(`
SELECT object_origin,
party_uuid AS company,
connection_uuid AS connection,
object_created AS object_creation_date,
"object_raw_origin_data.register_sales.sale_date" AS transaction_date,
"object_raw_origin_data.register_sales.total_price"
+ "object_raw_origin_data.register_sales.total_tax" AS transaction_gross_value,
"object_raw_origin_data.register_sales.total_price" AS transaction_net_value,
'goods-service-transaction' AS object_class,
'point-of-sale' AS object_origin_category,
'offline' AS object_origin_type,
object_origin AS object_origin,
"object_raw_origin_data.register_sales.invoice_number" AS transaction_reference,
"object_raw_origin_data.register_sales.status" AS transaction_status,
'GBP' AS transaction_currency,
"object_raw_origin_data.register_sales.sale_products.name" AS 'line_items.item_name'
FROM Vend_raw_transactions
`)
The query above works all except the last line which creates an object in the document called line_items but it isn't an array. The source is also an array.
Below is the Mongo script it creates for me:
db.Vend_raw_transactions.aggregate(
[{
"$project": {
"object_origin": "$object_origin",
"company": "$party_uuid",
"connection": "$connection_uuid",
"object_creation_date": "$object_created",
"transaction_date": "$object_raw_origin_data.register_sales.sale_date",
"transaction_gross_value": {
"$add": [
"$object_raw_origin_data.register_sales.total_price",
"$object_raw_origin_data.register_sales.total_tax"
]
},
"transaction_net_value":
"$object_raw_origin_data.register_sales.total_price",
"object_class": "goods-service-transaction",
"object_origin_category": "point-of-sale",
"object_origin_type": "offline",
"transaction_reference":
"$object_raw_origin_data.register_sales.invoice_number",
"transaction_status": "$object_raw_origin_data.register_sales.status",
"transaction_currency": "GBP",
"line_items.item_name":
"$object_raw_origin_data.register_sales.sale_products.name"
}
}])
Does anyone know why the last line isn't working for me?
"line_items.item_name": "$object_raw_origin_data.register_sales.sale_products.name"
I'm pretty sure I'm missing an [*] somewhere. Thanks, Matt
EDITED TO ADD example of Vend Transaction
{
"object_category" : "application",
"object_type" : "register-sales-24-months",
"object_origin" : "vend",
"tenant_uuid" : "00000000-0000-0009-9999-999999999999",
"party_uuid" : "8d519765-05d2-469f-ad35-d7a22fa9df2f",
"subscription_uuid" : "0",
"connection_uuid" : "6ed9bd79-d9c5-4296-a821-7e15b1c69e6c",
"status" : "",
"object_created" : ISODate("2018-03-15T21:40:57.158+0000"),
"object_raw_origin_data" : {
"pagination" : {
"results" : NumberInt(75964),
"page" : NumberInt(1),
"page_size" : NumberInt(200),
"pages" : NumberInt(380)
},
"register_sales" : {
"id" : "776a66f2-993c-b372-11e8-26f9bbe253f4",
"source" : "USER",
"source_id" : "",
"register_id" : "02dcd191-ae55-11e6-edd8-ec8dce1d9e1c",
"market_id" : "3",
"customer_id" : "02d59481-b67d-11e5-f667-b08185e8f6d5",
"customer_name" : "",
"customer" : {
"id" : "02d59481-b67d-11e5-f667-b08185e8f6d5",
"name" : "",
"customer_code" : "WALKIN",
"customer_group_id" : "02d59481-b67d-11e5-f667-b08185e893f8",
"customer_group_name" : "All Customers",
"updated_at" : "2016-01-01 12:16:44",
"deleted_at" : "",
"balance" : "0",
"year_to_date" : "0",
"date_of_birth" : "",
"sex" : "",
"custom_field_1" : "",
"custom_field_2" : "",
"custom_field_3" : "",
"custom_field_4" : "",
"note" : "",
"contact" : {
}
},
"user_id" : "02d59481-b655-11e5-f667-dca974edc4ea",
"user_name" : "Alvaro Velosa",
"sale_date" : "2018-03-13 20:04:57",
"created_at" : "2018-03-13 20:05:08",
"updated_at" : "2018-03-13 20:05:08",
"total_price" : 3.5,
"total_cost" : 2.74,
"total_tax" : NumberInt(0),
"tax_name" : "No Tax",
"note" : "",
"status" : "CLOSED",
"short_code" : "newa6f",
"invoice_number" : "Masonic2107Temple",
"accounts_transaction_id" : "",
"return_for" : "",
"register_sale_products" : [
{
"id" : "776a66f2-993c-b372-11e8-26f9cbf10f10",
"product_id" : "02dcd191-ae55-11e7-f130-9d4f4bcd91b1",
"register_id" : "02dcd191-ae55-11e6-edd8-ec8dce1d9e1c",
"sequence" : "0",
"handle" : "LAGERDRAUGHT300",
"sku" : "10287",
"name" : "LAGER DRAUGHT £3.00",
"quantity" : NumberInt(1),
"price" : 3.5,
"cost" : 2.74,
"price_set" : NumberInt(0),
"discount" : NumberInt(0),
"loyalty_value" : NumberInt(0),
"tax" : NumberInt(0),
"tax_id" : "02d59481-b67d-11e5-f667-b08185ec2871",
"tax_name" : "No Tax",
"tax_rate" : NumberInt(0),
"tax_total" : NumberInt(0),
"price_total" : 3.5,
"display_retail_price_tax_inclusive" : "0",
"status" : "CONFIRMED",
"attributes" : [
{
"name" : "line_note",
"value" : ""
}
]
}
],
"totals" : {
"total_tax" : NumberInt(0),
"total_price" : 3.5,
"total_payment" : 3.5,
"total_to_pay" : NumberInt(0)
},
"register_sale_payments" : [
{
"id" : "776a66f2-993c-b372-11e8-26f9cd75e9aa",
"payment_type_id" : "1",
"register_id" : "02dcd191-ae55-11e6-edd8-ec8dce1d9e1c",
"retailer_payment_type_id" : "02d59481-b655-11e5-f667-b0a23bc0e7bc",
"name" : "Cash",
"label" : "Account Customer",
"payment_date" : "2018-03-13 20:04:57",
"amount" : NumberInt(10)
},
{
"id" : "776a66f2-993c-b372-11e8-26f9cd7a3096",
"payment_type_id" : "1",
"register_id" : "02dcd191-ae55-11e6-edd8-ec8dce1d9e1c",
"retailer_payment_type_id" : "02d59481-b655-11e5-f667-b0a23bc0e7bc",
"name" : "Cash",
"label" : "Account Customer",
"payment_date" : "2018-03-13 20:04:57",
"amount" : -6.5
}
]
}
}
}
Use the $map operator to shape the field to an array by mapping the array elements to the item_name key:
"line_items": {
"$map": {
"input": "$object_raw_origin_data.register_sales.register_sale_products",
"as": "product",
"in": { "item_name": "$$product.name" }
}
}
Output
"line_items" : [
{
"item_name" : "LAGER DRAUGHT £3.00"
}
]

Resources