I have a table that contains documents that look similar to this:
{
"title": "title 2",
"content": "This far, no further!",
"category": "Fiction"
}
This is the query I'm using:
r.table('posts').group('title').map(lambda item:
{'items': item['title']}
).run())
This is the output:
{
"title 1" : [
{
"items" : "title 1"
},
{
"items" : "title 1"
}
],
"Title 2" : [
{
"items" : "Title 2"
},
{
"items" : "Title 2"
},
{
"items" : "Title 2"
},
{
"items" : "Title 2"
}
],
"title 3" : [
{
"items" : "title 3"
}
]
}
However I would like to get an output structure that looks like this:
{
"Title 1" : {
"item_count" : 3,
"items" : [
{
"items" : "title 1"
},
{
"items" : "title 1"
},
{
"items" : "title 1"
}
]
},
"Title 2" : {
"item_count" : 2,
"items" : [
{
"items" : "title 2"
},
{
"items" : "title 2"
}
]
},
"Title 3" : {
"item_count" : 1,
"items" : [
{
"items" : "title 3"
}
]
}
}
How would I create a query to get to this result.
In order to do that, you need to map your query after you executing ungroup in it.
First, the output of your first query looks incorrect. RethinkDB doesn't wouldn't return an object/dictionary after a map operation, it would return an array. The output I got from your query was the following:
[
{
"group": "title 1" ,
"reduction": [
{
"items": "title 1"
} ,
{
"items": "title 1"
}
]
} ,
{
"group": "title 2" ,
"reduction": [
{
"items": "title 2"
} ,
{
"items": "title 2"
}
]
} ,
...
]
If what you want is a property called items along with a count of how many items that items property has, you can do the following:
// THIS IS JAVASCRIPT
r.table('posts')
.group('title')
.map(function (item) {
return {
items: item('title')
}
})
.ungroup()
.map(function (row) {
return {
'title': row('group'),
'items': row('reduction'),
'count': row('reduction').count()
}
})
The result of that query will be the following:
[
{
"count": 2 ,
"items": [
{
"items": "title 1"
},
{
"items": "title 1"
}
],
"title": "title 1"
},
{
"count": 2 ,
"items": [
{
"items": "title 2"
} ,
{
"items": "title 2"
}
] ,
"title": "title 2"
},
...
]
If you want to then turn that query into an object/dictionary so that you can call up a post by it's title, you can turn that array of posts into an object, by using r.object along with r.args. The complete query will look like this:
// THIS IS JAVASCRIPT
r.table('posts')
.group('title')
.map(function (item) {
return {
items: item('title')
}
})
.ungroup()
.map(function (row) {
return {
'title': row('group'),
'items': row('reduction'),
'count': row('reduction').count()
}
})
.do(function (rows) {
return r.object(r.args(rows.concatMap(function (row) {
return [row('title'), row];
})));
})
The result of that query will be something like this:
{
"title 1": {
"count": 2 ,
"items": [
{
"items": "title 1"
} ,
{
"items": "title 1"
}
] ,
"title": "title 1"
} ,
"title 2": {
"count": 2 ,
"items": [
{
"items": "title 2"
} ,
{
"items": "title 2"
}
] ,
"title": "title 2"
} ,
...
}
Related
this seems to be a complex one - not sure if it's possible to manage without scripting + I would like to be able to boost name or value fields.
Let's imagine the following documents:
{
"name":"Red Big Blue document",
"nested_key_value_properties":[
{
"key":"description 1",
"value":"red"
},
{
"key":"description 2",
"value":"big"
},
{
"key":"description 3",
"value":"blue"
}
]
}
{
"name":"Black Small Red document",
"nested_key_value_properties":[
{
"key":"description 1",
"value":"red"
},
{
"key":"description 2",
"value":"small"
},
{
"key":"description 3",
"value":"black"
}
]
}
{
"name":"Yellow Big Red document",
"nested_key_value_properties":[
{
"key":"description 1",
"value":"yellow"
},
{
"key":"description 2",
"value":"big"
},
{
"key":"description 3",
"value":"red"
}
]
}
I wish to get the documents that have the key description 1 of the value of red only (first and second document) - the last document should not be in results.
TLDR;
Elastic flatten objects. Such that
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
Turn into:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
To avoid that you need to set the mapping manually by telling that nested_key_value_properties is going to be a nested field.
And then perform a nested query.
See below for how to do so.
To reproduce
PUT /71217348/
{
"settings": {},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"nested_key_value_properties": {
"type": "nested",
"properties": {
"key": {
"type": "keyword"
},
"value": {
"type": "keyword"
}
}
}
}
}
}
POST /_bulk
{"index":{"_index":"71217348"}}
{"name":"Red Big Blue document","nested_key_value_properties":[{"key":"description 1","value":"red"},{"key":"description 2","value":"big"},{"key":"description 3","value":"blue"}]}
{"index":{"_index":"71217348"}}
{"name":"Black Small Red document","nested_key_value_properties":[{"key":"description 1","value":"red"},{"key":"description 2","value":"small"},{"key":"description 3","value":"black"}]}
{"index":{"_index":"71217348"}}
{"name":"Yellow Big Red document","nested_key_value_properties":[{"key":"description 1","value":"yellow"},{"key":"description 2","value":"big"},{"key":"description 3","value":"red"}]}
GET /71217348/_search
{
"query": {
"nested": {
"path": "nested_key_value_properties",
"query": {
"bool": {
"must": [
{
"match": {
"nested_key_value_properties.key": "description 1"
}
},
{
"match": {
"nested_key_value_properties.value": "red"
}
}
]
}
}
}
}
}
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
}
])
In json schema, I can simply define a code list using "enum" with a list of code that is available, for example:
{
"type": "object",
"properties": {
"group": {
"type":"string",
"$ref": "#/definitions/Group"
}
},
"definitions": {
"Group": {
"enum": ["A","B"]
}
}
}
And the following payload would be valid:
{
"group": "B"
}
However, I try to provide the description in the schema to the user where "A" = "Group A", "B" = "Group B". Something like:
{
"type": "object",
"properties": {
"group": {
"type":"string",
"$ref": "#/definitions/Group"
}
},
"definitions": {
"Group": {
"enum": [
{"code":"A",
"description": "Group A"
},
{"code":"B",
"description": "Group B"
}
]
}
}
}
But I don't want to change the structure of the payload (no "description" field needed)
The description is more for documentation purposes that users can refer to.
Is there a good practice that can be used here?
Thank you
You can use anyOf with const instead of enum. Then you can use title or description for documentation.
{
"anyOf": [
{
"const": "A",
"title": "Group A"
},
{
"const": "B",
"title": "Group B"
}
]
}
It depends on your tool-chain. For example the jsonschema2md allows to use meta:enum attribute for descriptions:
{
"type": "object",
"properties": {
"group": {
"type":"string",
"$ref": "#/definitions/Group"
}
},
"definitions": {
"Group": {
"enum": ["A", "B"],
"meta:enum": {
"A": "Group A",
"B": "Group B"
}
}
}
}
I wanna create a tag cloud (or category list) which should link to the corresponding tagged articles and category. But in the queries I built only the name OR slug are concatenated because they are placed either in fields OR in frontmatter but not in one object
I use this two plugins which are widely used: https://github.com/rmcfadzean/gatsby-pantry
This is my current query:
{
tags: allMarkdownRemark(filter: {frontmatter: {title: {ne: ""}}}) {
group(field: frontmatter___tags) {
fieldValue
totalCount
edges {
node {
fields {
tags
}
frontmatter {
tags
}
}
}
}
}
}
{
"data": {
"allMarkdownRemark": {
"group": [
{
"fieldValue": "Another tag",
"totalCount": 1,
"edges": [
{
"node": {
"fields": {
"tags": [
"another-tag",
"my-example",
"post"
]
},
"frontmatter": {
"tags": [
"Another tag",
"My example",
"Post"
]
}
}
}
]
},
{
"fieldValue": "Example",
"totalCount": 1,
"edges": [
{
"node": {
"fields": {
"tags": [
"example",
"post"
]
},
"frontmatter": {
"tags": [
"Example",
"Post"
]
}
}
}
]
},
{
"fieldValue": "My example",
"totalCount": 1,
"edges": [
{
"node": {
"fields": {
"tags": [
"another-tag",
"my-example",
"post"
]
},
"frontmatter": {
"tags": [
"Another tag",
"My example",
"Post"
]
}
}
}
]
},
{
"fieldValue": "Post",
"totalCount": 2,
"edges": [
{
"node": {
"fields": {
"tags": [
"another-tag",
"my-example",
"post"
]
},
"frontmatter": {
"tags": [
"Another tag",
"My example",
"Post"
]
}
}
},
{
"node": {
"fields": {
"tags": [
"example",
"post"
]
},
"frontmatter": {
"tags": [
"Example",
"Post"
]
}
}
}
]
}
]
}
},
}
How can I get objects something like this:
{ "tags":
[
{ "slug": "another-tag", "frontmatter": "Another Tag"},
{ "slug": "example", "frontmatter": "Example"}
]
}
My current approach is in the view itself. I iterate through the fields.tags and search for them in the array. I save the index and use it for frontmatter.tags (they are happily in the same order)
It is exactly that code:
<ul className="tagcloud">
{tags.group.map((tag, idx) => {
var index = tag.edges[0].node.frontmatter.tags.indexOf(
tag.fieldValue
)
return (
<li key={idx}>
<Link
to={`/tags/${tag.edges[0].node.fields.tags[index]}`}
className="transition link"
>
{tag.fieldValue}
</Link>
</li>
)
})}
</ul>
I have a json document in elasticsearch complete/user with the following structure:
"_source":{
"experiences":[
{experience 1}, {experience 2}, ... , {experience n}
]
}
The structure of experience object in the experiences array is as follows:
{
"company":
{
"industry": industry of the comany,
"name": company name,
... other fields
},
"start_date": date when person joined company,
... other fields
}
I want to find all such documents where neither of the experiences in experiences array have company.industry field i.e. all the experiences must have this field missing. Is there any query that I can use?
Thanks in advance
Try this out:
{
"query": {
"bool": {
"must_not": [
{
"exists": {"field" : "experiences.company.industry"}
}
]
}
}
}
This query will return all the documents where company.industry of all experience in experiences array is missing or null.
Example:
"_source": {
"experiences": [
{
"company": {
"name": "company name"
}
},
{
"company": {
"industry": null,
"name": "company name"
}
}
]
}
What this query will not return:
"_source": {
"experiences": [
{
"company": {
"industry": "IT",
"name": "company name"
}
},
{
"company": {
"industry": null,
"name": "company name"
}
}
]
}
Let me know if that helped.