MongoDB get fieldvalue based on fieldname - mongodb-query

I'm new to MongoDB, and I'm not sure if what I'm trying to do is possible at all. I've exhausted my Google skills, so I'm hoping someone here can give me a push in the right direction.
My data is structured like this:
db={
"people": [
{
"id": 1,
"name": "Pete",
"occupation": "baker"
},
{
"id": 2,
"name": "Mike",
"occupation": "painter"
}
],
"activity": [
{
"baker": "bakes",
"painter": "paints"
}
]
}
Although this is just sample data, my "activity" is a single large document with unique keys that I'm trying to get the value from, based on key name (when it matches value from the "people" document).
What I'm trying to achieve is this output:
[
{
"id": 1,
"name": "Pete",
"occupation": "baker”,
“activity:” “bakes”
},
{
"id": 2,
"name": "Mike",
"occupation": "painter”,
“activity”: “paints”
}
]
Is this possible at all?

If I understand your database and data model, it seems like a poor model.
If the data model was different (see below), the query would be quite simple. Given that, here's one way you could generate your desired output with your model.
db.people.aggregate([
{ "$lookup": {
"from": "activity",
"let": { occ: "$occupation" },
"pipeline": [
{
"$replaceWith": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "kv",
"cond": { "$eq": [ "$$kv.k", "$$occ" ] }
}
}
}
}
],
"as": "activity"
}
},
{ "$set": {
"activity": {
"$getField": {
"field": "v",
"input": {
"$first": {
"$objectToArray": { "$first": "$activity" }
}
}
}
}
}
},
{ "$unset": "_id" }
])
Try it on mongoplayground.net.
If your activity collection has this model...
[
{
"occupation": "baker",
"activity": "bakes"
},
{
"occupation": "painter",
"activity": "paints"
}
]
... then the query could be:
db.people.aggregate([
{ "$lookup": {
"from": "activity",
"localField": "occupation",
"foreignField": "occupation",
"as": "activity"
}
},
{ "$set": { "activity": { "$first": "$activity.activity" } } },
{ "$unset": "_id" }
])
Try it on mongoplayground.net.

Related

Custom return MongoDB aggregate

I'm trying to do some testing with MongoDB and I have figured some of the simpler MySQL queries MongoDB. Now, I have this slightly more complex query.
I have this query that tells me if there was a message in a certain period from a determined user:
SELECT CASE WHEN count(1) = 0 THEN false ELSE true END AS 'value'
FROM messages m
WHERE m.time BETWEEN 0 AND 1652471890 AND m.user_id = '256f5280-fb49-4ad6-b7f5-65c4329d46e0';
Currently I am trying to do this to count the amount and emit a custom value 0/1:
Current MongoDB Aggregate
db.messages.aggregate([
{ $match:
{
$and: [
{user_id: "256f5280-fb49-4ad6-b7f5-65c4329d46e0"},
{time: {$gt: 1622471890, $lt: 1822471890}}
]
}
},
{ $count: "value"}
])
Dataset:
[
{
"time": 1422471890,
"user_id": "256f5280-fb49-4ad6-b7f5-65c4329d46e0",
"message": "This is an example of my db"
},
{
"time": 1622471890,
"user_id": "256f5280-fb49-4ad6-b7f5-65c4329d46e0",
"message": "This is an example of my db (1)"
},
{
"time": 1622471890,
"user_id": "256f5280-fb49-4ad6-b7f5-65c4329d46e0",
"message": "This is an example of my db (2)"
},
{
"time": 1622471890,
"user_id": "e194d667-d79f-4262-94b1-ecf4561c9418",
"message": "This is an example of my db (3)"
},
{
"time": 1922471890,
"user_id": "256f5280-fb49-4ad6-b7f5-65c4329d46e0"<
"message": "This is an example of my db (4)"
}
]
Return:
With this dataset it's returning:
{ "value" : 2 }
I'm trying make its return:
If count > 0:
{ "value": 1 }
If count <= 0:
{ "value": 0 }
You just need one more $addFields stage to apply $cond to your value
db.collection.aggregate([
{
$match: {
$and: [
{
user_id: "256f5280-fb49-4ad6-b7f5-65c4329d46e0"
},
{
time: {
$gte: 1622471890,
$lt: 1822471890
}
}
]
}
},
{
"$count": "value"
},
{
"$addFields": {
"value": {
"$cond": {
"if": {
"$gt": [
"$value",
0
]
},
"then": "$value",
"else": 0
}
}
}
},
{
"$unionWith": {
"coll": "collection",
"pipeline": [
{
$limit: 1
}
]
}
},
{
"$sort": {
value: -1
}
},
{
$limit: 1
},
{
"$project": {
_id: 0,
value: {
"$ifNull": [
"$value",
0
]
}
}
}
])
Here is the Mongo Playground for your reference.

MongoDB Lookup values based on dynamic field name

I'm pretty sure the below can be done, I'm struggling to understand how to do it in MongoDB.
My data is structured like this (demo data):
db={
"recipes": [
{
"id": 1,
"name": "flatbread pizza",
"ingredients": {
"1010": 1,
"1020": 2,
"1030": 200
}
},
{
"id": 2,
"name": "cheese sandwich",
"ingredients": {
"1040": 1,
"1050": 2
}
}
],
"ingredients": [
{
"id": 1010,
"name": "flatbread",
"unit": "pieces"
},
{
"id": 1020,
"name": "garlic",
"unit": "clove"
},
{
"id": 1030,
"name": "tomato sauce",
"unit": "ml"
},
{
"id": 1040,
"name": "bread",
"unit": "slices"
},
{
"id": 1050,
"name": "cheese",
"unit": "slices"
}
]
}
The output I'm trying to achieve would look like this:
[
{
"id": 1,
"name": "flatbread pizza",
“flatbread”: “1 pieces”,
“garlic”: “2 cloves”,
“tomato sauce”: “200 ml”
},
{
"id": 2,
"name": "cheese sandwich",
“bread”: “1 slices”,
“cheese”: “2 slices”
}
]
I've tried several approaches, and I get stuck at the bit where I need to do a lookup based on the ingredient name (which actually is the id). I tried using $objectToArray to turn it into a k-v document, but then I get stuck in how to construct the lookup pipeline.
This is not a simple solution, and probably can be improved:
db.recipes.aggregate([
{
"$addFields": {
ingredientsParts: {
"$objectToArray": "$ingredients"
}
}
},
{
$unwind: "$ingredientsParts"
},
{
"$group": {
_id: "$id",
name: {
$first: "$name"
},
ingredientsParts: {
$push: {
v: "$ingredientsParts.v",
id: {
$toInt: "$ingredientsParts.k"
}
}
}
}
},
{
"$lookup": {
"from": "ingredients",
"localField": "ingredientsParts.id",
"foreignField": "id",
"as": "ingredients"
}
},
{
$unwind: "$ingredients"
},
{
"$addFields": {
"ingredientsPart": {
"$filter": {
input: "$ingredientsParts",
as: "item",
cond: {
$eq: [
"$$item.id",
"$ingredients.id"
]
}
}
}
}
},
{
$project: {
ingredients: 1,
ingredientsPart: {
"$arrayElemAt": [
"$ingredientsPart",
0
]
},
name: 1
}
},
{
"$addFields": {
units: {
k: "$ingredients.name",
v: {
"$concat": [
{
$toString: "$ingredientsPart.v"
},
" ",
"$ingredients.unit"
]
}
}
}
},
{
$group: {
_id: "$_id",
name: {
$first: "$name"
},
units: {
$push: "$units"
}
}
},
{
"$addFields": {
"data": {
"$arrayToObject": "$units"
}
}
},
{
"$addFields": {
"data.id": "$_id",
"data.name": "$name"
}
},
{
"$replaceRoot": {
"newRoot": "$data"
}
}
])
You can see it works here
As rickhg12hs said, it can be modeled better.

Querying an Array in Graphql

I have the following query on graphql
query articles {
articles {
news_link
article_details {
description
title
brands {
name
}
featured_image {
url
}
published_at
}
}
}
Which will give me the following sample response
{
"data": {
"articles": [
{
"news_link": "http://loanstreet.com.my",
"article_details": [
{
"description": "My first article",
"title": "First Article",
"brands": [
{
"name": "Fendi"
}
],
"featured_image": {
"url": "/uploads/e5c00dbd3a3648dd8c0e1c2a44f50c0d.png"
},
"published_at": "2020-03-31T04:00:00.000Z"
},
{
"description": "Lighter ff article",
"title": "First Article LP",
"brands": [
{
"name": "Lighter"
}
],
"featured_image": {
"url": "/uploads/ac6c5f26050f46eebd37fa7319ab531b.png"
},
"published_at": "2020-03-31T04:00:00.000Z"
}
]
}
]
}
}
I am trying to query and only get the response where brand name is "Fendi" but cannot seem to get it right using Graphql playground.
I tried this
query articles {
articles {
news_link
article_details {
description
title
brands(where: {name: "Fendi"}) {
name
}
featured_image {
url
}
published_at
}
}
}
but it gave me this response which is not really what i want
{
"data": {
"articles": [
{
"news_link": "http://loanstreet.com.my",
"article_details": [
{
"description": "My first article",
"title": "First Article",
"brands": [
{
"name": "Fendi"
}
],
"featured_image": {
"url": "/uploads/e5c00dbd3a3648dd8c0e1c2a44f50c0d.png"
},
"published_at": "2020-03-31T04:00:00.000Z"
},
{
"description": "Lighter ff article",
"title": "First Article LP",
"brands": [],
"featured_image": {
"url": "/uploads/ac6c5f26050f46eebd37fa7319ab531b.png"
},
"published_at": "2020-03-31T04:00:00.000Z"
}
]
}
]
}
}
I am expecting a response like this
{
"data": {
"articles": [
{
"news_link": "http://loanstreet.com.my",
"article_details": [
{
"description": "My first article",
"title": "First Article",
"brands": [
{
"name": "Fendi"
}
],
"featured_image": {
"url": "/uploads/e5c00dbd3a3648dd8c0e1c2a44f50c0d.png"
},
"published_at": "2020-03-31T04:00:00.000Z"
}
]
}
]
}
}
Any help is appreciated. Thanks

Create a new Google Sheet with row or column groups

I'm trying to create a new spreadsheet using spreadsheets#create, with specified row groups.
In the API Explorer, I am entering in the JSON below. which corresponds to the following appearance:
No errors are flagged or returned when I execute the call, but when the sheet is created, the specified grouping is not created - only the values are set.
{ "properties": {
"title": "Test Spreadsheet",
"locale": "en"
},
"sheets": [
{ "properties": {"title": "Test1"},
"data": [
{
"startRow": 0,
"startColumn": 0,
"rowData": [
{ "values": [
{ "userEnteredValue": { "stringValue": "Top1" } }
]
},
{ "values": [
{ "userEnteredValue": { "stringValue": "Top2" } }
]
},
{ "values": [
{ "userEnteredValue": { "stringValue": "" } },
{ "userEnteredValue": { "stringValue": "Top2A" } }
]
},
{ "values": [
{ "userEnteredValue": { "stringValue": "" } },
{ "userEnteredValue": { "stringValue": "Top2B" } }
]
},
{ "values": [
{ "userEnteredValue": { "stringValue": "" } },
{ "userEnteredValue": { "stringValue": "Top2C" } }
]
},
{ "values": [
{ "userEnteredValue": { "stringValue": "Top3" } }
]
}
]
}
],
"rowGroups": [
{ "range": {
"dimension": "ROWS",
"startIndex": 2,
"endIndex": 5
}
}
]
}
]
}
Even when I create the rowGroups JSON directly on the page, with its structured editor to make sure it is properly defined, the created spreadsheet still doesn't group the specified rows. I have triple-checked all my objects from the top down, and can't see what I am doing wrong.

Creating a Mango query selector for element that do NOT match

I have a user like so:
{
"_id": "u88888",
"_rev": "27-9f205fb7496645be2f3d717fff376d73",
"name": "Test Testerson",
"type": "user",
"role": "boss",
"training": [
{
"id": "11111",
"name": "training 1"
},
{
"id": "33333",
"name": "training 3"
}
]
}
I'm trying to run a query to find the following:
Is a type, "user"
Has a role of "boss"
Does not have the training of id: "11111"
I do the following selector, however, this user comes up and I'm not sure why:
selector:{
"$and": [
{ "type": "user" },
{ "role": "boss" },
{ "training": { "$ne": { "id": "11111" } } }
]
}
Found an answer. This ended up working:
{ training: { $not: {$elemMatch: {id: "11111" } } }