I have some documents in my collection like below
{
"_id": "xxxxxxxxx",
"Keyword Group A": [
"Facebook",
"Twitter"
],
"Keyword Group B": [
"Netflix"
]
},
{
"_id": "yyyyyyy",
"Keyword Group A": [
"Twitter"
],
"Keyword Group B": [
"Instagram",
],
...
}
I can fetch all documents whose Keyword Group A contains "Facebook", by below filter
$filter: {
input: "$Keyword Group A",
as: "group",
cond: { $eq: ["$$group", "Facebook"] },
}
But If I want to fetch all documents if Keyword Group A contains "Facebook" OR Keyword Group B contains "Instagram", how should I adjust the filters?
I am not sure why you need to use $filter because your requirement will fulfill just by equal to a condition in $match stage or in query,
{
$match: {
$or: [
{
"Keyword Group A": "Facebook"
},
{
"Keyword Group B": "Instagram"
}
]
}
}
Playground
Related
I have a dictionary field in my data like so:
"details": {
"code": "PPIO",
"product": [{
"productCode": "ADGT"
}]
}
I need to convert the field to an array of objects:
"details":
[
{
"code": "PPIO",
"product": [{
"productCode": "ADGT"
}]
}
]
You can use $addFields to overwrite existing field:
db.collection.aggregate([
{
$addFields: {
details: [ "$details" ]
}
}
])
Mongo Playground
EDIT:
For update you can use below syntax:
db.col.updateMany({}, [{ $set: { details: [ "$details" ] } }])
EDIT 2:
Alternatively, if updateMany doesn't work for you, you can use $out operator which will replace your collection entirely with an aggregation outcome:
db.collection.aggregate([
{
$addFields: {
details: [ "$details" ]
}
},
{ $out: "collection" }
])
I have the following query and it works with $in but not with $nin.
I'm trying to remove the link list items by name (itemA and itemB) from all records that are NOT part of a document that has a user name which contains '#not_these' or '#nor_these'.
db.users.update({userName:{$nin: [ RegExp('#not_these.com'), RegExp('#nor_these.com') ]}},{$pull:{'myLinkList': {name: {$in: ['itemA', 'itemB']} } } } )
If I make it $in and and declare the RegExp() explicitly it does remove the array items as expected.
db.users.update({userName:{$in: [ RegExp('#yes_these.com'), RegExp('#and_these.com') ]}},{$pull:{'myLinkList': {name: {$in: ['itemA', 'itemB']} } } } )
This one does remove itemA and itemB array list items for those explicitly declared users.
Why can't the items '#yes_these' and '#and_these' be removed using the first example? It seems to do nothing when executed.
Sample document:
{
"_id": ObjectId('5e34741aa18d8a0c24078b61'),
"myLinkList": [
{
"name": "item",
"created": ISODate('2020-01-31T18:38:18.682Z'),
"managedBy": [
"imm"
]
},
{
"name": "itemA",
"created": ISODate('2020-01-31T18:38:18.682Z'),
"managedBy": [
"imm"
]
},
{
"name": "itemB",
"created": ISODate('2020-01-31T18:38:18.682Z'),
"managedBy": [
"imm"
]
}
],
"userName": "#yes_these.com"
}
After update (hopefully):
{
"_id": ObjectId('5e34741aa18d8a0c24078b61'),
"myLinkList": [
{
"name": "item",
"created": ISODate('2020-01-31T18:38:18.682Z'),
"managedBy": [
"imm"
]
}
],
"userName": "#yes_these.com"
}
I verified this did work:
db.users.updateMany({userName:{$nin: [ /#not_these\.com/), /#nor_these\.com/) ]}},{$pull:{'myLinkList': {name: {$in: ['itemA', 'itemB']} } } } )
We have two collections, Teams and Matches. Every time a Match is reported, a new document is saved in that collection and its added to an array in the Team documents (teams[i].matches).
A now solved bug in our system has caused that the new Matches document were not referenced in their respectives Teams documents.
Is there a query for Mongo DB 3.6.9 that can help us find the Matches not referenced in Teams?
An aggregation pipeline may help you, using $lookup.
$lookup fetches documents from "Teams" that match the pipeline's $match.
let: { match_id: "$_id" } create a variable match_id corresponding to Match's _id.
$match expression keeps only Teams with match_id into Team's matches array.
as: "matches" stores Team that validate previous $match.
Last $match after $lookup step keeps matches array that are empty (Matches with no Teams)
db.Matches.aggregate([
{
$lookup: {
from: "Teams",
let: { match_id: "$_id" },
pipeline: [{
$match: {
$expr: {
$in: [ "$$match_id", "$matches" ]
}
}
}],
as: "matches"
},
},
{
$match: {
$expr: { $eq: [{ $size: "$matches" }, 0] }
}
}
]);
This has been tested with the following collection template and Mongo playground online editor :
db={
"Matches": [
{ "_id": 0 },
{ "_id": 1 },
{ "_id": 2 },
{ "_id": 3 },
{ "_id": 4 },
],
"Teams": [
{
"_id": 0,
matches: [ 0, 3 ],
},
{
"_id": 1,
matches: [],
},
{
"_id": 2,
matches: [ 0 ],
},
{
"_id": 3,
matches: [ 2 ],
}
]
}
The resulting output is :
[
{
"_id": 1,
"matches": []
},
{
"_id": 4,
"matches": []
}
]
I want find in this document groups:
"document": {
"groups": [
{
"id": "5ccd5f7f34f82b0e3315b2f6"
},
{
"id": "73b43unbfkfmdmddfdf84jjk"
}
]
}
are contains some of my query array groups ID:
[ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ]
A simple find query suffices:
db.collection.find({ 'groups.id' : {$in : [ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ] }})
I would like to perform a join on a collection where student name are equal in each collection AND WHERE the last string after "_" in column log's value is what the variable id is.
I got the join to work but the issue is on the match statement. How can I match with a substring of a string on the logs column in the collection that I am about to join?
I can split the log column value into an array like this:
{ $split: [ "$studentInfo.log", "_" ]}
I just need to get the last value after underscore now to match variable id
var id = "123";
dbo.collection("student").aggregate([
{ "$lookup": {
"localField": "name",
"from": "data",
"foreignField": "data.studentName",
"as": "studentInfo"
}
}]).toArray(function(err, results) {
console.log(results);
});
The issue is that student name is not unique so in order to get the join to work correctly we need to join by name AND make sure the characters after underscore match with the variable we have id
student collection
{
"_id" : ObjectId("(Object ID here"),
"name": "Test"
}
data collection
{
"_id" : ObjectId("(Object ID here"),
"studentName": "Test",
"log": "NC_Test_123"
},
{
"_id" : ObjectId("(Object ID here"),
"studentName": "Test",
"log": "FC_Test_444"
}
I need to get NC_Test_123 when the variable I have for id is 123.
You need to define custom lookup condition with both conditions: student name and log field. To get the last value of splitted string you can use $arrayElemAt with index set to -1
db.student.aggregate([
{
$lookup: {
from: "data",
let: { "student_name": "$name" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: [ "$$student_name", "$studentName" ] },
{ $eq: [ { $arrayElemAt: [ { $split: [ "$log", "_" ]}, -1 ] }, "123" ] }
]
}
}
}
],
as: "studentInfo"
}
},
{
$unwind: "$studentInfo"
}
])