I am a graphql noob and the first query I have to write turned to be a complex one. Imagine this is the object I'm looking for
{
name : "ferrari"
year : "1995"
}
Now, there is a nested object in which this could be present, The object could look like this
{
"name": "car",
"year": "1990",
"morecars": [
{
"name": "ferrari",
"year": "1995"
},
{
"name": "bmw",
"year": "200"
}
]
}
or this
{
"name": "car",
"year": "1990",
"morecars": [
{
"name": "red",
"year": "1990",
"morecares": [
{
"name": "ferrari",
"year": "1995"
}
]
},
{
"name": "bmw",
"year": "200"
}
]
}
How do fetch the ferrari i need
Related
I am new to the mongoDB aggregation and I have this situation. I have this Json and I need to convert by "select" this object:
{
"type": "PF",
"code": 12345
"Name": Darth Vader,
"currency": "BRL",
"status": "SINGLE",
"adress": [
{
"localization": "DEATH STAR",
"createDate": 1627990848665
},
{
"localization": "TATOOINE",
"createDate": 1627990555665
},
]
}
this way:
{
"type": "PF",
"code": 12345
"Name": Darth Vader,
"currency": "BRL",
"status": "SINGLE",
"localization": "DEATH STAR",
"createDate": 1627990848665
},
{
"type": "PF",
"code": 12345
"Name": Darth Vader,
"currency": "BRL",
"status": "SINGLE",
"localization": "TATOOINE",
"createDate": 1627990555665
}
So, after my query is complete, I will have 02 objects instead of 01. How can I do this?
I would like to do this via select because after converting I will sort by createDate and limit the number of records to return to the API. I'm using Criteria em my project.
The way to do this is $unwind, this will make 1 copy of the document, for each member of the array.
Test code here
db.collection.aggregate([
{
"$unwind": {
"path": "$user.adress"
}
},
{
"$set": {
"user": {
"$mergeObjects": [
"$user",
"$user.adress"
]
}
}
},
{
"$unset": [
"user.adress"
]
},
{
"$sort": {
"createDate": 1
}
},
{
"$limit": 10
}
])
Edit1 (the above is if user is a field, if it was the name of the collection)
$$ROOT is a system variable that has as value all the document
Test code here
Query
db.collection.aggregate([
{
"$unwind": {
"path": "$adress"
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$$ROOT",
"$adress"
]
}
}
},
{
"$unset": [
"adress"
]
},
{
"$sort": {
"createDate": 1
}
},
{
"$limit": 10
}
])
I have an elasticsearch document with some nested objects(mapped as nested field)
for example:
{
"FirstName": "Test",
"LastName": "Test",
"Cost": 322.54,
"Email": "test#test.com",
"Vehicles": [
{
"Year": 2000,
"Make": "Mazda",
"Model": "6"
},
{
"Year": 2012,
"Make": "Ford",
"Model": "F150"
}
]
}
i am trying to do aggregations on specific index of the array, for example i want to sum the cost of documents which has Ford make but only on the first vehicle.
is it even possible at all? there is almost no information on the internet about elasticsearch nested fields and nothing about their index/order
It is possible to achieve what you want, but you also need to add the index order as a field inside your nested documents:
{
"FirstName": "Test",
"LastName": "Test",
"Cost": 322.54,
"Email": "test#test.com",
"Vehicles": [
{
"Year": 2000,
"Make": "Mazda",
"Model": "6",
"Index": 0
},
{
"Year": 2012,
"Make": "Ford",
"Model": "F150",
"Index": 1
}
]
}
And then you can query your index using the two conditions on Index and the Make like this:
{
"query": {
"nested": {
"path": "Vehicles",
"query": {
"bool": {
"filter": [
{
"match": {
"Vehicles.Index": 0
}
},
{
"match": {
"Vehicles.Make": "Ford"
}
}
]
}
}
}
}
}
In this specific case, the query is not going to yield any results, as you expect.
Shortly: when a field has multiple values, how can I get only those items where both my filter applies to the SAME value in a multiple-values field?
Details
I have stored in Elasticsearch some items which have a nested field with multiple values, e.g.
"hits": [
{
"name": "John",
"tickets": [
{
"color": "green",
"code": "001"
},
{
"color": "red",
"code": "002"
}
]
},
{
"name": "Frank",
"tickets": [
{
"color": "red",
"code": "001"
},
{
"color": "green",
"code": "002"
}
]
}
]
Now consider these filters:
...
filter: [
{ terms: { 'tickets.code': '001' } },
{ terms: { 'tickets.color': 'green' } },
]
...
Both items match, because each one of them has at least a ticket with code "001" and each one of them has ticket with color "green".
How do I write my filters so that only the first match, because it has a ticket which has code "001" AND color "green"?
Thank you in advance for any suggestion.
Your problem is caused by the fact that Elasticsearch flattens objects. So internally, your data is represented something like this:
{
"name": "John",
"tickets.color": ["green", "red"],
"tickets.code": ["001", "002"]
},
{
"name": "Frank",
"tickets.color": ["red", "green"],
"tickets.code": ["001", "002"]
}
It's impossible to know which color and code are on the same object. (The original source is also stored, in order to be returned when you make a request, but that's not the data that's queried when you search.)
There are two potential solutions here: denormalization, or nested data type. If you can at all get away with it, denormalization is the better choice here, because it's more efficient. If you denormalize your data, you might end up with a representation like this:
{
"name": "John",
"ticket": {
"color": "green",
"code": "001"
}
},
{
"name": "John",
"ticket": {
"color": "red",
"code": "002"
}
},
{
"name": "Frank",
"ticket": {
"color": "red",
"code": "001"
}
},
{
"name": , "Frank",
"ticket": {
"color": "green",
"code": "002"
}
}
If you use a nested data type, you'll have to use a mapping something like this:
{
"ticket": {
"type": "nested",
"properties": {
"color": {"type": "keyword"},
"code": {"type": "keyword"}
}
}
}
When using the sample POSTMAN request:
{
"idempotency_key": "74ae1696-b1e3-4328-af6d-f1e04d947a13",
"order": {
"reference_id": "my-order-001",
"line_items": [
{
"name": "line-item-1",
"quantity": "1",
"base_price_money": {
"amount": 1599,
"currency": "USD"
}
},
{
"name": "line-item-2",
"quantity": "2",
"base_price_money": {
"amount": 799,
"currency": "USD"
}
}]
},
"ask_for_shipping_address": true,
"merchant_support_email": "merchant+support#website.com",
"pre_populate_buyer_email": "buyer#email.com",
"pre_populate_shipping_address": {
"address_line_1": "500 Electric Ave",
"address_line_2": "Suite 600",
"locality": "New York",
"administrative_district_level_1": "NY",
"postal_code": "10003",
"first_name": "Jane",
"last_name": "Doe"
},
"redirect_url": "https://merchant.website.com/order-confirm"
}
I'm getting the following response:
{
"errors": [
{
"category": "INVALID_REQUEST_ERROR",
"code": "INVALID_VALUE",
"detail": "The order must have at least one line item.",
"field": "line_items"
}]
}
This is simply executing the sample POSTMAN requests available via https://docs.connect.squareup.com/api/connect/v2/#runningpostman
I was having the same issue and I reached out to Tristan. Tristan replied there was a bug that square development had to fix. I confirmed that the create checkout API is now working properly so this issue should be resolved now.
Are you using your sandbox or production access tokens? I was able to generate a checkout form with the example postman request:
{
"idempotency_key": "73ae1696-b1e3-4328-af6d-f1e04d947a13",
"order": {
"reference_id": "my-order-001",
"line_items": [
{
"name": "line-item-1",
"quantity": "1",
"base_price_money": {
"amount": 1599,
"currency": "USD"
}
},
{
"name": "line-item-2",
"quantity": "2",
"base_price_money": {
"amount": 799,
"currency": "USD"
}
}
]
},
"ask_for_shipping_address": true,
"merchant_support_email": "merchant+support#website.com",
"pre_populate_buyer_email": "buyer#email.com",
"pre_populate_shipping_address": {
"address_line_1": "500 Electric Ave",
"address_line_2": "Suite 600",
"locality": "New York",
"administrative_district_level_1": "NY",
"postal_code": "10003",
"first_name": "Jane",
"last_name": "Doe"
},
"redirect_url": "https://merchant.website.com/order-confirm"
}
So assuming that i have a mapping structure like the following
{
"mappings": {
"users": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
}
and I have indexed the following
users/52
{
"user": [
{
"id": 52,
"first": "John",
"last": "Smith",
"age": 21,
"school": {
"name": "STC",
"location": "Mt LV",
"District": "Western"
}
}
]
}
users/57
{
"user": [
{
"id": 57,
"first": "Alice",
"last": "White",
"age": 25,
"school": {
"name": "HFC",
"location": "DEH WLA",
"District": "Western"
}
}
]
}
What if I want to get certain fields using the id and without destroying the relationship link of each other.
For an example
If id == 57
then the return structure should consists only "first","age","school.name","school.District"
{
"user": [
{
"first": "Alice",
"age": 25,
"school": {
"name": "HFC",
"District": "Western"
}
}
]
}
How should you write a query for this sort of response in Elasticsearch?
Use response filtering in Elasticsearch. According to your scenario, a GET request would look like GET /_search?user=57&filter_path=first,age,school.name,school.District