Cosmos DB: how to project properties into array and group them? - azure-cosmosdb

Using this sample data consisting of 3 separate documents in the same container:
{
"id" : "doc1",
"manager" : "John",
"country": "Germany"
}
{
"id" : "doc2",
"manager" : "John",
"country": "Netherlands"
}
{
"id" : "doc3",
"manager" : "Jack",
"country": "Austria"
}
I would like to write a query that returns a list of objects containing the distinct manager names and the countries they're responsible for. Something in the shape of:
[
{
"manager": "John",
"countries": ["Germany", "Netherlands"]
},
{
"manager": "Jack",
"countries": ["Austria"]
}
]
I have tried (and failed) with joins, subqueries, and JSON object projections.

Related

Firestore data modeling

I am creating a new Firestore database and am new to NoSQL. I am creating an application where I would need 4 root collections. Users, teams, challenges, and tournaments. Users need to join teams. Admins need to create challenges and tournaments. Tournaments need challenges and participants. I was wondering how this could be modeled the best in Firestore. This is what it looks like in JSON format so far:
{
"users": {
"uid": "user_id",
"firstName": "John",
"lastName": "Doe"
},
"teams": {
"members": {
"user_id": {
"uid": "user_id",
"firstName": "John",
"lastName": "Doe"
}
},
"teamName": "Team X",
"teamPhoto": "url"
},
"challenges": {
"doc1": {
"challengeName": "name",
"challengeDescription": "description"
}
},
"tournaments": {
"selectedChallenges": [
{
"challenge_doc1": {
"challengeName": "name",
"challengeDescription": "description"
}
}
],
"tournamentName": "name"
}
}

JSONPath Export Key & Value

I am using JSONPath to filter out a json file, I am trying to retrieve both the Key + Value from the JSON array but I am lost at figuring how best to do this.
QUERY
$.phoneNumbers[*].[type,number]
ARRAY
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888",
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
},
{
"type" : "home",
"number": "0123-4567-8910",
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
}
]
}
CURRENT OUTPUT
[
"iPhone",
"0123-4567-8888",
"home",
"0123-4567-8910"
]
Desired Outcome
[
{
"type" : "iPhone",
"number": "0123-4567-8888",
},
{
"type" : "home",
"number": "0123-4567-8910",
}
]
What you're looking for can't be done with JSON Path because you're looking to transform the data. JSON path is only going to give you the values in a flat list.
You might find some luck with JMES Path. It's pretty similar, but I'm less familiar with it.
You likely need to add quotes
$.phoneNumbers[*].['type','number']

Nested query in Firebase Firestore

I have a Firestore database structure like this:
(Articles is a collection, everything inside is arrays)
Articles:
[
{
"id": 1,
"reports": [
{
"locations": [
{
"location": "Sydney",
"country": "Australia"
},
{
"location": "Perth",
"country": "Australia"
}
],
},
{
"locations": [
{
"location": "King County, Washington",
"country": "USA"
}
],
}
]
},
{
"id": 2,
"reports": [
{
"locations": [
{
"location": "Brisbane",
"country": "Australia"
}
]
}
]
}
]
I'd like to create a query to return all Articles that mention a specific country.
Am I better off restructuring my database?
While Firestore's array-contains queries can get you close to this, you can't use them in your current data model as you're nesting arrays.
To allow the use-case you'll at the very least need to unnest one of those arrays into a subcollection of each article, so:
Articles (collection)
$article
reports (collection)
$report (document with a locations array)
At that point you can use a collection group query to search all reports collections, and then array-contains to find the relevant report documents:
var ref = firebase.firestore().collectionGroup("reports");
ref.where("locations", "array-contains", { location: "Sydney", country: "Australia" })
Never mind the below answer, which assumed you had only one level of array...
This type of query should be possible, as far as I can see, using the array-contains operator. Keeping in mind that you need to specify the entire array item.
So something like:
collectionRef.where("reports.locations", "array-contains",
{ location: "Sydney", country: "Australia" })

Which firstname field is always returned in request to Linkedin V2 API?

When I request user details from LinkedIn’s V2 People endpoint I get the below:
Which first name and last name attribute can I use to save the user details? Is localizedLastName always returned?
{
"localizedLastName": "abc",
"lastName": {
"localized": {
"en_US": "abc"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"firstName": {
"localized": {
"en_US": "abc"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:C5103AQGrCbjMGgxnzQ"
},
"id": "226262627",
"localizedFirstName": "abc"
}
Hi Use this to receive the first name and last name
$profile['firstName']=array_pop($array['firstName']['localized']);
$profile['lastName']=array_pop($array['lastName']['localized']);

WHERE clause on an array in Azure DocumentDb

In an Azure Documentdb document like this
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 1,
"pets": [
{ "givenName": "Goofy" },
{ "givenName": "Shadow" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 8
}
],
"address": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
};
How do I query to get children whose pets given name is "Goofy" ?
Looks like the following syntax is invalid
Select * from root r
WHERE r.children.pets.givenName="Goofy"
Instead I need to do
Select * from root r
WHERE r.children[0].pets[0].givenName="Goofy"
which is not really searching through an array.
Any suggestion on how I should handle queries like these ?
You should take advantage of DocumentDB's JOIN clause, which operates a bit differently than JOIN in RDBMs (since DocumentDB deals w/ denormlaized data model of schema-free documents).
To put it simply, you can think of DocumentDB's JOIN as self-joins which can be used to form cross-products between nested JSON objects.
In the context of querying children whose pets given name is "Goofy", you can try:
SELECT
f.id AS familyName,
c AS child,
p.givenName AS petName
FROM Families f
JOIN c IN f.children
JOIN p IN c.pets
WHERE p.givenName = "Goofy"
Which returns:
[{
familyName: WakefieldFamily,
child: {
familyName: Merriam,
givenName: Jesse,
gender: female,
grade: 1,
pets: [{
givenName: Goofy
}, {
givenName: Shadow
}]
},
petName: Goofy
}]
Reference: http://azure.microsoft.com/en-us/documentation/articles/documentdb-sql-query/
Edit:
You can also use the ARRAY_CONTAINS function, which looks something like this:
SELECT food.id, food.description, food.tags
FROM food
WHERE food.id = "09052" or ARRAY_CONTAINS(food.tags.name, "blueberries")
I think the ARRAY_CONTAINS function has changed since this was answered in 2014. I had to use the following for it to work.
SELECT * FROM c
WHERE ARRAY_CONTAINS(c.Samples, {"TimeBasis":"5MIN_AV", "Value":"5.105"},true)
Samples is my JSON array and it contains objects with many properties including the two above.

Resources