Select specifics items from array objects in mongoose - arrays

I have an mongoDB objetc like :
[
{
"items": [
{
"title": "hello",
"options": [
{
"value": "A",
"image": "img1",
"des": "des1"
},
{
"value": "B",
"image": "img2",
"des": "des2"
},
]
}
]
}
]
When I retrieve data from the collection, I want to retrieve only value key from the options of the items array.
Output should look like :
{
"items":[
{
"options" :[
{ "value" :"A" },
{ "value" :"B" },
]
}
]
}
How can i do this?

You can do it like this:
db.collection.find({}, { "items.options.value": 1})
Here is the working example: https://mongoplayground.net/p/FqDaQ7Q-y-Y
Or you can do it like this:
db.collection.aggregate([
{
"$project": {
"items.options.value": 1
}
}
])
Here is the working example: https://mongoplayground.net/p/jPFYtXYBvpI

Related

Join collection with array object field with another collection in MongoDB

I'm working in MongoDB and getting stuck at one aggregation case. Let me show you my collection.
First collection (data):
[
{
"_id": "8e7b3fa0-4230-448c-8f70-1d7300632834",
"data": [
{
"animal" : "7d44251a-b308-4deb-875a-33ef0a69fe2b",
"place": "Chennai"
},
{
"animal" : "fcfdd527-5885-48b0-a91f-03f72f78528f",
"place": "Kolkata"
}
]
}
]
Second collection (Animal):
[
{
"_id": "7d44251a-b308-4deb-875a-33ef0a69fe2b",
"name": "Dog"
},
{
"_id": "7d44251a-b308-4deb-875a-33ef0a69fe2b",
"name": "Cat"
}
]
I'm using this query:
db.data.aggregate([
{
"$lookup": {
"from": "animal",
"localField": "data.animal",
"foreignField": "_id",
"as": "doc"
}
},
{
"$unwind": "$doc"
},
{
"$project": {
"_id": 1,
"data.animal": "$doc.name",
"data.place": 1
}
}
])
and it result me this
[
{
"_id": "8e7b3fa0-4230-448c-8f70-1d7300632834",
"data": [
{
"animal": "Dog",
"place": "Chennai"
},
{
"animal": "Dog",
"place": "Kolkata"
}
]
},
{
"_id": "8e7b3fa0-4230-448c-8f70-1d7300632834",
"data": [
{
"animal": "Cat",
"place": "Chennai"
},
{
"animal": "Cat",
"place": "Kolkata"
}
]
}
]
Where I'm expecting like this
[
{
"_id": "8e7b3fa0-4230-448c-8f70-1d7300632834",
"data": [
{
"animal": "Dog",
"place": "Chennai"
},
{
"animal": "Cat",
"place": "Kolkata"
}
]
}
]
Mongo Playground
Also sharing this question in Mongo playgroud. Thanks in advance!!
Solution 1
$unset - Deconstruct the data array into multiple documents.
$lookup - Perform join with animal collection.
$project - Decorate the output document. For data.animal field, get the first value via $first.
$group - Group by _id. Push the data document into the data array.
db.data.aggregate([
{
"$unwind": "$data"
},
{
"$lookup": {
"from": "animal",
"localField": "data.animal",
"foreignField": "_id",
"as": "doc"
}
},
{
"$project": {
"_id": 1,
"data.animal": {
$first: "$doc.name"
},
"data.place": 1
}
},
{
$group: {
_id: "$_id",
data: {
$push: "$data"
}
}
}
])
Demo Solution 1 # Mongo Playground
Solution 2
$lookup
$set - Set data field.
2.1. $map - Iterate the data array and returns a new array.
2.1.1. $mergeObjects - Merge current iterated document with place field and the document from 2.1.1.1.
2.1.1.1. $first - Get the first document from the filtered doc arrays by matching the ids via $filter.
$unset - Remove _id and animals._id fields.
db.data.aggregate([
{
"$lookup": {
"from": "animal",
"localField": "data.animal",
"foreignField": "_id",
"as": "doc"
}
},
{
$set: {
data: {
$map: {
input: "$data",
as: "data",
in: {
$mergeObjects: [
{
place: "$$data.place"
},
{
$first: {
$filter: {
input: "$doc",
cond: {
$eq: [
"$$this._id",
"$$data.animal"
]
}
}
}
}
]
}
}
}
}
},
{
$unset: [
"doc",
"data._id"
]
}
])
Demo Solution 2 # Mongo Playground

MongoDB get only selected elements from objects inside an array

What I have is a collection of documents in MongoDB that have the structure something like this
[
{
"userid": "user1",
"addresses": [
{
"type": "abc",
"street": "xyz"
},
{
"type": "def",
"street": "www"
},
{
"type": "hhh",
"street": "mmm"
},
]
},
{
"userid": "user2",
"addresses": [
{
"type": "abc",
"street": "ccc"
},
{
"type": "def",
"street": "zzz"
},
{
"type": "hhh",
"street": "yyy"
},
]
}
]
If I can give the "type" and "userid", how can I get the result as
[
{
"userid": "user2",
"type": "abc",
"street": "ccc",
}
]
It would also be great even if I can get the "street" only as the result. The only constraint is I need to get it in the root element itself and not inside an array
Something like this:
db.collection.aggregate([
{
$match: {
userid: "user1" , "address.type":"abc"
}
},
{
$project: {
userid: 1,
address: {
$filter: {
input: "$addresses",
as: "a",
cond: {
$eq: [
"$$a.type",
"abc"
]
}
}
}
}
},
{
$unwind: "$address"
},
{
$project: {
userid: 1,
street: "$address.street",
_id: 0
}
}
])
explained:
Filter only documents with the userid & addresess.type you need
Project/Filter only the addresses elements with the needed type
unwind the address array
project only the needed elements as requested
For best results create index on the { userid:1 } field or compound index on { userid:1 , address.type:1 } fields
playground
You should be able to use unwind, match and project as shown below:
db.collection.aggregate([
{
"$unwind": "$addresses"
},
{
"$match": {
"addresses.type": "abc",
"userid": "user1"
}
},
{
"$project": {
"_id": 0,
"street": "$addresses.street"
}
}
])
You can also duplicate the match step as the first step to reduce the number of documents to unwind.
Here is the playground link.
There is a similar question/answer here.

$in Query on Array Field Mongo db

I have a doc like this
{
"_id" : "oidfi",
"users": [
{
"_id": "q",
"tags": ["a", "b", "c"],
"age": 20
},
{
"_id": "q",
"tags": ["x", "y", "z"],
"age": 30
}
],
"type": "repo"
}
I want to filter the users array with several fields ( I'm able to do that with the below query )
{
"$match": {
"$and": [
{
"_id": "a506f8af6f510f616bea14715276d474d2b363f0aef10443cc0f11559b139147"
}
]
}
},
{
"$project": {
"users": {
"$filter": {
"input": "$users",
"as": "users",
"cond": {
"$and": [
{
"$gte": [
"$$user.age",
15
]
}
]
}
}
}
}
}
]
is there a way for me to add condition where I give a list of tags items and get the users who are matching at least one item from their tags array
$$user.tags.containsAny(["a", "x"])
Thanks
You can do the followings in an aggregation pipeline:
$setIntersection to find out the intersection of the users.tags array and your input array i.e. ["a", "x"] in your example
$size to find the size of array in step 1
$match by the size of step 2 larger than 0
"anyTagsMatched": {
$gt: [
{
$size: {
"$setIntersection": [
"$users.tags",
[
"a",
"x"
]
]
}
},
0
]
}
Here is the Mongo playground for your reference.
You may have like following
db.collection.aggregate([
{
"$project": {
"users": {
"$filter": {
"input": "$users",
"cond": {
"$and": [
{ "$gte": [ "$$this.age", 15 ] },
{
$gt: [
{
$size: {
"$setIntersection": [
"$$this.tags",
[ "a", "x" ]
]
}
},
0
]
}
]
}
}
}
}
}
])
Working Mongo playground

Split arrays in set mongodb

I've been trying to make a set of strings < or arrays > but my main issue is that I can't use $unwind because of the other data.
To make it more clear I'll show an example:
This is how part of my documents look like:
{
"key": [
"a",
"b",
"c"
]
},
{
"key": [
"b",
"d"
]
},
{
"key": [
"e"
]
}
And I want to get an array like this:
{
"keys": [
"a",
"b",
"c",
"d",
"e"
]
}
or this:
{
"keys": [
["a"],
["b"],
["c"],
["d"],
["e"]
]
}
I just need unique values in there.
It would be so easy if I could use $unwind and then $addToSet. But as I said before I can't because of the other data that I need.
I was trying to use $cond inside the $addToSet but I don't know how to iterate through an array.
This pipeline doesn't work ->
db.collection.aggregate([
{
"$group": {
"_id": null,
"keys": {
"$addToSet": {
"$concatArrays": [
"$key",
"$this"
]
}
},
}
}
])
Maybe something like this:
{
"$group": {
"_id": null,
"keys": {
"$addToSet": {
"$cond": {
if: {
"$gt": [
{"$size": "$key"},
1
]
},
then: "<SPLIT THE ARRAY IN THE AMOUNT OF ELEMENTS>",
else: "$key"
}
}
}
}
}
I tried this but it doesn't work either.
db.collection.aggregate([
{
"$project": {
"keys": {
"$map": {
"input": {
"$range": [
0,
{
"$size": "$key"
},
1
]
},
as: "index",
in: {
$slice: [
"$key",
"$$index",
1
]
}
}
}
}
},
{
"$group": {
"_id": null,
"keys": {
"$addToSet": {
"$concatArrays": [
"$keys"
]
}
},
}
}
])
Here is my code snippet: https://mongoplayground.net/p/sMENXyrbQgI
Could someone please guide me! I'll appreciate it so much.
So the idea is to use $setUnion along with $reduce to pick unique values from the array:
Solution in MongoPlayground
Try this query:
db.collection.aggregate([
{
$group: {
_id: null,
"keys": { $push: "$key" }
}
},
{
$addFields: {
"keys": {
$reduce: {
input: "$keys",
initialValue: [],
in: {
$setUnion: ["$$value", "$$this"]
}
}
}
}
}
])
Output:
{
"_id" : null,
"keys" : [
"a",
"b",
"c",
"d",
"e"
]
}
Test data in collection:
[
{
"key": [
"a",
"b",
"c"
]
},
{
"key": [
"b",
"d",
"a",
]
},
{
"key": [
"e",
"b"
]
}
]

how to angular JS get complex json

i need to take child array in this json . i tried too many ways, how can i take kindC -> name . Plz help !!
Full map:
[
{
"direction": {
"book": "A",
"note": "B"
},
"prize": {
"kindA": [],
"kindB": [],
"kindC": [{
"name": "Target#1",
"_id": "32131"
}]
},
]
}
Just access the prize object
console.log(data[0].prize.kindC);
if you need to access the 1st object
console.log(data[0].prize.kindC[0].name);
DEMO
var data = [
{
"direction": {
"book": "A",
"note": "B"
},
"prize": {
"kindA": [],
"kindB": [],
"kindC": [
{
"name": "Target#1",
"_id": "32131"
}
]
}
}
];
console.log(data[0].prize.kindC[0].name);
DEMO
var jsonObj = [
{
"direction": {
"book": "A",
"note": "B"
},
"prize": {
"kindA": [],
"kindB": [],
"kindC": [
{
"name": "Target#1",
"_id": "32131"
}
]
}
}
];
console.log(jsonObj[0].prize.kindC[0].name);

Resources