MongoDB query for objects in an array - mongodb

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

Related

Getting concrete elements by element field in 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

Query free timeslots in MongoDB using unix timestamps

I'm new to MongoDB and probably this is a common use case, but I didn't find an answer to this specific case.
I would like to filter out those MongoDB documents where a timeslot in booking is still free, so there is no overlapping with existing bookings.
My collection entries:
{
"_id": "5efc9f89749c983ffd58c55f",
"training": "football",
"bookings": [
{
"from": 1593607419,
"to": 1593622800
}
]
},
{
"_id": "5efc9f89749c983ffd58c55f",
"training": "baseball",
"bookings": [
{
"from": 1593607419,
"to": 1593622800
},
{
"from": 1593687419,
"to": 1593722800
}
]
}
Expected result with input "From: 1593500000" and "To: 1593600000".
{
"_id": "5efc9f89749c983ffd58c55f",
"training": "football"
},
{
"_id": "5efc9f89749c983ffd58c55f",
"training": "baseball"
}
Both documents have free timeslots (no overlapping with existing bookings).
Expected result with input "From: 1593670000" and "To: 1593690000".
{
"_id": "5efc9f89749c983ffd58c55f",
"training": "football"
}
Only football is returned, because the queried values overlaps with the second booking entry of baseball.
Is it possible to do this with a single query? For example using between or something like that?
Or is there a better approach/best practice?
I implement the query with Spring Data REST, but just some help with the mongodb query would already be very helpful.
This is more of a logical problem, I'm not familiar with Spring Data, your query should look like this.
{
bookings: {
$not: {
$elemMatch: {
$or: [{
from: { $gte: start, $lte: end }
}, {
to: { $gte: start, $lte: end }
}]
}
}
}
}
Mongo Playground

mongodb aggregation - nested group

I'm trying to perform nested group, I have an array of documents that has two keys (invoiceIndex, proceduresIndex) I need the documents to be arranged like so
invoices (parent) -> procedures (children)
invoices: [ // Array of invoices
{
.....
"procedures": [{}, ...] // Array of procedures
}
]
Here is a sample document
{
"charges": 226.09000000000003,
"currentBalance": 226.09000000000003,
"insPortion": "",
"currentInsPortion": "",
"claim": "notSent",
"status": "unpaid",
"procedures": {
"providerId": "9vfpjSraHzQFNTtN7",
"procedure": "21111",
"description": "One surface",
"category": "basicRestoration",
"surface": [
"m"
],
"providerName": "B Dentist",
"proceduresIndex": "0"
},
"patientId": "mE5vKveFArqFHhKmE",
"patientName": "Silvia Waterman",
"invoiceIndex": "0",
"proceduresIndex": "0"
}
Here is what I have tried
https://mongoplayground.net/p/AEBGmA32n8P
Can you try the following;
db.collection.aggregate([
{
$group: {
_id: "$invoiceIndex",
procedures: {
$push: "$procedures"
},
invoice: {
$first: "$$ROOT"
}
}
},
{
$addFields: {
"invoice.procedures": "$procedures"
}
},
{
"$replaceRoot": {
"newRoot": "$invoice"
}
}
])
I retain the invoice fields with invoice: { $first: "$$ROOT" }, also keep procedures's $push logic as a separate field. Then with $addFields I move that array of procedures into the new invoice object. Then replace root to that.
You shouldn't use the procedureIndex as a part of _id in $group, for you won't be able to get a set of procedures, per invoiceIndex then. With my $group logic it works pretty well as you see.
Link to mongoplayground

MongoDB moving array of sub-documents to it's own collection

I'm looking to move an array of subdocuments into a collection of it's own keyed by the owner id. Currently, my collection is formed like this:
"_id": ObjectId("123"),
"username": "Bob Dole",
"logins": [{
"_id": ObjectId("abc123"),
"date": ISODate("2016")
}, {
"_id": ObjectId("def456"),
"date": ISODate("2016")
}]
I'm looking for the best way to write a script that would loop over each user, and move each item in the logins array to it's own "logins" collection, as follows:
{
"_id": ObjectId("abc123"),
"_ownerId": ObjectId("123"),
"date": ISODate("2016")
}
{
"_id": ObjectId("def567"),
"_ownerId": ObjectId("123"),
"date": ISODate("2016")
}
When the script ends, I'd like the login array to be removed entirely from all users.
this query will create new collection using aggregation framework
to see how it looks - just remove $out pipeline phase
db.thinking.aggregate([
{
$unwind:"$logins"
},{
$project:{
_id:"$logins._id",
_ownerId:"$_id",
date:"$logins.date"
}
},
{
$out: "newCollection"
}
])
to delete array records - as suggested in comment:
db.thinking.update({},{ "$unset": { "logins": "" } },{ "multi": true })

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!