I have model named Shop which has name, image. There is possibility that there will be multiple shops with the same name.
For example if I have these shops:
[{_id: "1", name: "Shop A", image: "ImageShopA.jpg"},
{_id: "2", name: "Shop A", image: "ImageShopA1.jpg"},
{_id: "3", name: "Shop B", image: "ImageShopB.jpg"},
{_id: "4", name: "Shop B", image: "ImageShopB1.jpg"},
{_id: "5", name: "Shop C", image: "ImageShopC.jpg"}]
I want to get this kind of result:
[{name: "Shop A", ids: ["1", "2"], image: "ImageShopA.jpg"},
{name: "Shop B", ids: ["3", "4"], image: "ImageShopB.jpg"},
{name: "Shop C", ids: ["5"], image: "ImageShopC.jpg"}]
It creates JSON Objects which has ids of grouped models which are grouped by name and get image of first found model.
Is it possible to do that with aggregation?
Yes, its possible. If you run the following aggregation pipeline in mongo shell with the given data sample
db.collection.aggregate([
{
"$sort": {
"_id": 1
}
},
{
"$group": {
"_id": "$name",
"ids": {
"$push": "$_id"
},
"image": {
"$first": "$image"
}
}
},
{
"$project": {
"name": "$_id", "ids": 1, "image": 1
}
}
])
you will get the desired results:
/* 0 */
{
"result" : [
{
"_id" : "Shop C",
"ids" : [
"5"
],
"image" : "ImageShopC.jpg",
"name" : "Shop C"
},
{
"_id" : "Shop B",
"ids" : [
"3",
"4"
],
"image" : "ImageShopB.jpg",
"name" : "Shop B"
},
{
"_id" : "Shop A",
"ids" : [
"1",
"2"
],
"image" : "ImageShopA.jpg",
"name" : "Shop A"
}
],
"ok" : 1
}
You would need to convert this to the appropriate ruby implemenation
Related
TablesA, TableB, TableC
After joining the tables: TableA, TableB, TableC using Kusto Query how to show the value of column: IsPriLoc in the column: PriLoc and IsSecLoc in SecLoc. Below is the expected result
ExpectedResult
I made a couple of assumptions (regarding data types for example) but this query delivers the required results:
Link to execute on Kusto help cluster
let A = datatable (GUID_PK: string, Name: string, Desc: string) [
"1", "Test1", "Desc1",
"2", "Test2", "Desc2",
"3", "Test3", "Desc3",
"4", "Test4", "Desc4",
"5", "Test5", "Desc5",
"6", "Test6", "Desc6"
];
let B = datatable (GUID_FK: string, PriLoc: string, SecLoc: string) [
"1", "PriLoc1", "SecLoc1",
"3", "PriLoc3", "SecLoc3",
"5", "PriLoc5", "SecLoc5",
];
let C = datatable (GUID_FK: string, IsPriLoc: string, IsSecLoc: string) [
"2", "TRUE", "FALSE",
"4", "FALSE", "TRUE",
"6", "TRUE", "FALSE",
];
let BC = B
| union (
C
| project GUID_FK, PriLoc=IsPriLoc, SecLoc=IsSecLoc);
A
| join BC on $left.GUID_PK == $right.GUID_FK
I have a set of Author nodes. An Author node is the single parent of multiple Book nodes.
My goal: To print all Author nodes with no order and no limit, with each authors' first three books in alphabetical order.
Desired output: (let's pretend book names are a single letter)
[
{
"name" : "Leo Tolstoy",
"books": [
{ "name": "A" },
{ "name": "B" },
{ "name": "D" }
]
},
{
"name": "Charles Dickens",
"books": [
{ "name": "C" },
{ "name": "E" },
{ "name": "F" }
]
},
{
"name": "Oscar Wilde
...
]
My Problem:
I tried this:
MATCH(author:Author)
WITH author
OPTIONAL MATCH(author)-[:WROTE]->(book:Book)
WITH author, book
ORDER BY book.name
LIMIT 3
WITH author, collect(book) AS books
RETURN collect (
{
name: author.name,
books: books
}
);
But this gives:
[
{
"name" : "Leo Tolstoy",
"books": [
{ "name": "A" },
{ "name": "B" },
]
},
{
"name": "Charles Dickens",
"books": [
{ "name": "C" }
]
}
]
How could I achieve my desired output in Neo4j v3.5?
[EDITED]
This should work:
MATCH(author:Author)
OPTIONAL MATCH(author)-[:WROTE]->(book:Book)
WITH author, book.name AS bookName
ORDER BY bookName
WITH author, COLLECT({name: bookName})[..3] AS bookNames
RETURN COLLECT({name: author.name, books: bookNames}) AS result
I am trying to retrieve nodes and related nodes from a Neo4J dbase where i also want to dynamically add properties to the returned nodes. I have the following model: a Country contains Cities, i have the
following sample data:
CREATE (n:Country { identifier: '20f95f76-be40-4cff-98c8-8d045b0552eb', revision: '1', countryCode: 'BE', name: 'Belgium', type:'Country' });
CREATE (n:Country { identifier: '4c78a5b2-7fe6-4b8c-bd35-f2a0aa0ec160', revision: '1', countryCode: 'NL', name: 'Netherlands', type:'Country' });
CREATE (n:Country { identifier: 'aa265519-4765-477d-99f9-c65bf0c202d8', revision: '1', countryCode: 'DE', name: 'Germany', type:'Country' });
CREATE (n:City { identifier: '8147f29c-39f2-4123-9b73-298de2b871f9', revision: '1', name: 'Antwerp', type:'City' })
CREATE (n:City { identifier: '8058bfc4-9fd3-4df7-8035-0adb53da713c', revision: '1', name: 'Brussels', type:'City' })
MATCH (country:Country), (city:City)
WHERE country.identifier = '20f95f76-be40-4cff-98c8-8d045b0552eb' AND city.identifier = '8147f29c-39f2-4123-9b73-298de2b871f9'
CREATE (country)-[:CONTAINS]->(city)
MATCH (country:Country), (city:City)
WHERE country.identifier = '20f95f76-be40-4cff-98c8-8d045b0552eb' AND city.identifier = '8058bfc4-9fd3-4df7-8035-0adb53da713c'
CREATE (country)-[:CONTAINS]->(city)
What I would like to get out of the database is the Country nodes as well as the City nodes, but i need to add a "city" property to the Country node that is returned which contains an array of the identifiers of the contained city. And instead of storing the _type property, i would like to add it dynamically based on the label of the node.
Currently i am using the following query:
MATCH (country:Country)
OPTIONAL MATCH (country)-[:CONTAINS]-(city:City)
RETURN country {.*, city: collect( distinct city.identifier )}, city {.*, container: country.identifier}
I get the following results:
[
{
"country": {
"city": [
"8058bfc4-9fd3-4df7-8035-0adb53da713c"
],
"name": "Belgium",
"identifier": "20f95f76-be40-4cff-98c8-8d045b0552eb",
"revision": "1",
"countryCode": "BE",
"type": "Country"
},
"city": {
"container": "20f95f76-be40-4cff-98c8-8d045b0552eb",
"identifier": "8058bfc4-9fd3-4df7-8035-0adb53da713c",
"name": "Brussels",
"revision": "1",
"type": "City"
}
},
{
"country": {
"city": [
"8147f29c-39f2-4123-9b73-298de2b871f9"
],
"name": "Belgium",
"identifier": "20f95f76-be40-4cff-98c8-8d045b0552eb",
"revision": "1",
"countryCode": "BE",
"type": "Country"
},
"city": {
"container": "20f95f76-be40-4cff-98c8-8d045b0552eb",
"identifier": "8147f29c-39f2-4123-9b73-298de2b871f9",
"name": "Antwerp",
"revision": "1",
"type": "City"
}
},
{
"country": {
"city": [],
"name": "Netherlands",
"identifier": "4c78a5b2-7fe6-4b8c-bd35-f2a0aa0ec160",
"revision": "1",
"countryCode": "NL",
"type": "Country"
},
"city": null
},
{
"country": {
"city": [],
"name": "Germany",
"identifier": "aa265519-4765-477d-99f9-c65bf0c202d8",
"revision": "1",
"countryCode": "DE",
"type": "Country"
},
"city": null
}
]
As you can see, the Belgium node is returned twice (i was expecting it to be returned only once), each time there is a match on contained City. I do want to return the Country nodes even if they don't contain cities.
Some help would be appreciated
This query might be suitable:
MATCH (country:Country)
OPTIONAL MATCH (country)-[:CONTAINS]-(city:City)
RETURN country, COLLECT(city) AS cities
The result is:
╒══════════════════════════════════════════════════════════════════════╤══════════════════════════════════════════════════════════════════════╕
│"country" │"cities" │
╞══════════════════════════════════════════════════════════════════════╪══════════════════════════════════════════════════════════════════════╡
│{"name":"Belgium","identifier":"20f95f76-be40-4cff-98c8-8d045b0552eb",│[{"name":"Antwerp","identifier":"8147f29c-39f2-4123-9b73-298de2b871f9"│
│"type":"Country","countryCode":"BE","revision":"1"} │,"type":"City","revision":"1"},{"name":"Brussels","identifier":"8058bf│
│ │c4-9fd3-4df7-8035-0adb53da713c","type":"City","revision":"1"}] │
├──────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Netherlands","identifier":"4c78a5b2-7fe6-4b8c-bd35-f2a0aa0ec1│[] │
│60","type":"Country","countryCode":"NL","revision":"1"} │ │
├──────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Germany","identifier":"aa265519-4765-477d-99f9-c65bf0c202d8",│[] │
│"type":"Country","countryCode":"DE","revision":"1"} │ │
└──────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────┘
I have the following structure:
"countries": [
{
"states" :[
{
"name" :"Texas",
"id": "a1"
},
{
"name" :"Nebraska",
"id": "a1"
}
]
},
{
"states" :[
{
"name" :"New York",
"id": "a1",
},
{
"name" :"Florida",
"id": "a1"
}
]
}
]
I want to return an array of all the states from above.
Here is what I tried:
countries.map { |country| country.states.map { |state| state.name } }
But it returns only the first 2 statest 'Texas' and Nebraska.
Can someone tell me what I am doing wrong here?
you structure wasn't right, so corrected:
countries = [
{
"states" => [
{
"name" => "Texas",
"id"=> "a1"
},
{
"name"=> "Nebraska",
"id"=> "a1"
}
]
},
{
"states" => [
{
"name"=> "New York",
"id"=> "a1",
},
{
"name" =>"Florida",
"id"=> "a1"
}
]
}
]
Ruby wasn't accepting ":" for strings for some weird reasons. Like this(which isn't working):
countries = [
{
"states": [
{
"name": "Texas",
"id": "a1"
},
{
"name": "Nebraska",
"id": "a1"
}
]
},
{
"states": [
{
"name": "New York",
"id": "a1",
},
{
"name" :"Florida",
"id": "a1"
}
]
}
]
For this, you can do:
countries.map{ |c| c["states"].map{|s| s["name"]}}.flatten
#=> ["Texas", "Nebraska", "New York", "Florida"]
Or if you get the repetitive values then:
countries.map{ |c| c["states"].map{|s| s["name"]}}.flatten.uniq
#=> ["Texas", "Nebraska", "New York", "Florida"]
I hope this helps.
Go for Surya's answer, it is the same solution. Just wanna show how I write it:
countries.map{|x|x['states']}
.flatten
.map{|x|x['name']}
I have objects that look like:
[<ltree_val: "1", contents: "blah">,
<ltree_val: "1.1", contents: "blah">,
<ltree_val: "1.1.1", contents: "blah">,
<ltree_val: "2", contents: "blah">,
<ltree_val: "2.1", contents: "blah">]
Where ltree_val determines their tree structure.
I need to generate something like...
[{ "data" : "1",
"children" :
[{ "data" : "1.1",
"children" :
[{ "data" : "1.1.1" }]
}]
},
{ "data" : "2" }]
Where I have children which are determined by an ltree value, which are themselves elements of the same object.
If I sort these objects by their ltree value, how can I create nested entries?
I'm open to either RABL or JBuilder. I'm totally lost.
The answer was to use a recursive function...
# encoding: UTF-8
def json_ltree_builder( json, ltree_item )
json.title t( ltree_item.title )
json.attr do
json.id ltree_item.id
end
json.metadata do
json.val1 ltree_item.val1
json.val2 ltree_item.val2
end
children = ltree_item.children
unless children.empty?
json.children do
json.array! children do |child|
json_ltree_builder( json, child )
end
end
end
end
json.array! #menu_items do |menu_item|
json_ltree_builder( json, menu_item )
end
This builds something like
[
{ "title":"Title 1",
"attr" : {
"id": 111
},
"data" : {
"val1" : "Value 1",
"val2" : "Value 2"
},
"children" : [
{
"title":"Child 1",
"attr" : {
"id": 112
},
"data" : {
"val1" : "Value 1",
"val2" : "Value 2"
}
},
{
"title":"Child 2",
"attr" : {
"id": 112
},
"data" : {
"val1" : "Value 1",
"val2" : "Value 2"
}
}
]
}
]