Getting concrete elements by element field in mongoDB - mongodb

I know that by the title it is not very clear what is my problem, so let me explain it with an example.
Let's suppose I have a collection in a mongo database called tweets whose elements look like this:
{
"id": "tweet_id",
"text": "this is the tweet's text",
"user": {
"id": "user_id",
"name": "user_name",
}
}
Let's suppose that we have 100 documents that look like that, and 10 users with diferent ids and names.
How would look a query to know see the different user_id s that exist in the collection and their names?
The result I want would look like this:
{"user_id1": "user_name1"}
{"user_id2": "user_name2"}
...
{"user_id10": "user_name10"}
Thank you for your help

You can use this aggregation query:
First $group by user.id to get all differents user ids with the name.
And then use $replaceRoot with $arrayToObject to get the desired output format.
db.collection.aggregate([
{
"$group": {
"_id": "$user.id",
"name": {
"$first": "$user.name"
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[
{
"k": "$_id",
"v": "$name"
}
]
]
}
}
}
])
Example here

Related

Mongodb get document that has max value for each subdocument

I have some data looking like this:
{'Type':'A',
'Attributes':[
{'Date':'2021-10-02', 'Value':5},
{'Date':'2021-09-30', 'Value':1},
{'Date':'2021-09-25', 'Value':13}
]
},
{'Type':'B',
'Attributes':[
{'Date':'2021-10-01', 'Value':36},
{'Date':'2021-09-15', 'Value':14},
{'Date':'2021-09-10', 'Value':18}
]
}
I would like to query for each document the document with the newest date. With the data above the desired result would be:
{'Type':'A', 'Date':'2021-10-02', 'Value':5}
{'Type':'B', 'Date':'2021-10-01', 'Value':36}
I managed to find some queries to find over all sub document only the global max. But I did not find the max for each document.
Thanks a lot for your help
Storing date as string is generally considered as bad pratice. Suggest that you change your date field into date type. Fortunately for your case, you are using ISO date format so some effort could be saved.
You can do this in aggregation pipeline:
use $max to find out the max date
use $filter to filter the Attributes array to contains only the latest element
$unwind the array
$project to your expected output
Here is the Mongo playground for your reference.
This keeps 1 member from Attributes only, the one with the max date.
If you want to keep multiple ones use the #ray solution that keeps all members that have the max-date.
*mongoplayground can lose the order, of fields in a document,
if you see wrong result, test it on your driver, its bug of mongoplayground tool
Query1 (local-way)
Test code here
aggregate([
{
"$project": {
"maxDateValue": {
"$max": {
"$map": {
"input": "$Attributes",
"in": { "Date": "$$this.Date", "Value": "$$this.Value" },
}
}
},
"Type": 1
}
},
{
"$project": {
"Date": "$maxDateValue.Date",
"Value": "$maxDateValue.Value"
}
}
])
Query2 (unwind-way)
Test code here
aggregate([
{
"$unwind": { "path": "$Attributes" }
},
{
"$group": {
"_id": "$Type",
"maxDate": {
"$max": {
"Date": "$Attributes.Date",
"Value": "$Attributes.Value"
}
}
}
},
{
"$project": {
"_id": 0,
"Type": "$_id",
"Date": "$maxDate.Date",
"Value": "$maxDate.Value"
}
}
])

Robomongo query to return a list of ids

I want to query my database in Mongo and then be able to copy and paste the list of ids the query returns.
I know I can project the _id like
db.getCollection('mymodel').find({}}, { _id: 1 })
But I want to be able to copy and paste the result as an array of ids, is there a way to achieve this with Robomongo/Mongo?
Is this query you want?
Using aggregate add all _ids to a set:
db.collection.aggregate([
{
"$group": { "_id": null, "ids": { "$addToSet": "$_id" } }
},
{
"$project": { "_id": 0 }
}
])
And the ouput is similar to this, an array called ids with all id:
"ids": [
ObjectId("5a934e000102030405000000"),
ObjectId("5a934e000102030405000004"),
ObjectId("5a934e000102030405000001"),
ObjectId("5a934e000102030405000005"),
ObjectId("5a934e000102030405000003"),
ObjectId("5a934e000102030405000002")
]
You can use $match to filter the documents you want to get the id like this example.

MongoDB query for objects in an array

I have a collection that consists of objects like this:
{
"name": "Event One",
"user_id": "1"
"rsvp": [
{"id": "1","name":"John Doe","industry":"Software"},
{"id": "2","name":"John Doe II","industry":"Software"},
]
}
I am trying to query all events that a user has rsvp too and that he did not create. Then match the rsvp with the industry the are in. Is it possible to query in mongoDB and have it returned like this:
[
{"id": "1","name":"John Doe"},
{"id": "2","name":"John Doe II"},
]
The query I have is below:
events.find({"$and":[{"rsvp.contact.indusrty":{"$in":["Software","Information Systems"]}},{"user_id":{"$ne":"5d335704802df000076bad97"}}]},{"projection":{"rsvp.contact.name":true},"typeMap":{"root":"array","document":"array"}})
I am new to MONGODB and can't seem to find anything that is helping me figure this out.
You need $match to define filtering criteria, $unwind to get single document per rsvp and $replaceRoot to promote rsvp to root model:
db.events.aggregate([
{
$match: {
"$and":[
{
"rsvp.industry":{
"$in":["Software","Information Systems"]
}
},
{ "user_id":{"$ne":"5d335704802df000076bad97"}}
]
}
},
{
$unwind: "$rsvp"
},
{
$replaceRoot: {
newRoot: "$rsvp"
}
},
{
$project: {
industry: 0
}
}
])
Mongo Playground

How to find MongoDB records that have matching values in an array

I am tracking user IP's by adding them to an array on the user document like so:
{
"_id": "LafnHzmQL6rBmXNxJ",
"name": "someuser",
"displayName": "SomeUser",
"knownIPs": ["1.1.1.1", "2.2.2.2", "3.3.3.3"]
}
How can I find any documents where any 1 of the knownIPs match any 1 of the knownIPs in another (without specifying a particular value) regardless of what the actual IP is.
The goal is to identify people who are using multiple accounts so they can be flagged programmatically for further inspection. I have over 40,000 users, will this be too intensive of an aggregation?
Use the following aggregation pipeline:
db.collection.aggregate([
{ "$unwind": "$knownIPs" },
{
"$group": {
// Group by the IP address
"_id": "$knownIPs",
// Count number of matching docs for the group
"count": { "$sum": 1 },
// Save the _id for matching docs
"docs": { "$push": "$_id" }
}
},
{
"$match": {
"count": { "$gt": 1 }
}
}
])
I think you should use $unwind function on the array of knownIPs. so that it will give you three child object from parent object.
For example:
db.document_name.aggregate( [ { $unwind : "$knownIPs" } ] ) gives you
{
"_id": "LafnHzmQL6rBmXNxJ",
"name": "someuser",
"displayName": "SomeUser",
"knownIPs": "1.1.1.1"
}
{
"_id": "LafnHzmQL6rBmXNxJ",
"name": "someuser",
"displayName": "SomeUser",
"knownIPs": "2.2.2.2"
}
{
"_id": "LafnHzmQL6rBmXNxJ",
"name": "someuser",
"displayName": "SomeUser",
"knownIPs": "3.3.3.3"
}
After unwind operation, perform GroupBy operation on all the objects generated from unwind operation. So it will give the number of users who have same Ip.

Mongodb aggregate to find if a user is in any other user's follower list

I collected followers list and friends list for n number of users from twitter and stored them in mongodb.
Here is a sample document:
{
"_id": ObjectId("561d6f8986a0ea57e51ec95c"),
"status": "True",
"UserId": "1489245878",
"followers": [
"1566382441",
"1155774331"
],
"followersCount": 2,
"friendsCount": 5,
"friends": [
"1135511478",
"998082481",
"565321118",
"848123988",
"343334562"
]
}
I wanted to know within my collection, are there any userids that are also in the followers list of some other documents. Lets say we have user "a", now i would like to know if user "a" is in the followers list of any other document within the same collection. I'm not sure how to do this. In case if we have, i would like to project the userid and the _id of the document that has the userid within the followers list.
I guess you can use aggregate function like below to get this result.
db.getCollection('your_collection").aggregate([
{
"$match": {
"followers": "1566382441"
}
},
{
"$project": {
"followers": 1
}
},
{
"$unwind": "$followers"
},
{
"$match": {
"followers": "1566382441"
}
},
{
"$group": {
"_id": "$followers",
"ids": {
"$addToSet": "$_id"
}
}
},
{
"$project": {
"userId": "$_id",
"ids": 1,
"_id": 0
}
}
])
I am using only a sample of your data. You can add your list of users for whom you are trying to filter in both stages of "$match". Just see if this helps.
P.S: I know its been a long time since you asked this question! But you know, its never late!