MongoDB, how to filter based on previous record's date value - mongodb

I am not sure this is possible to achieve, I just want to be certain.
I have sorted dates records, for example:
{id: 1, date: 2015-08-18T00:00:00Z },
{id: 2, date: 2015-08-18T00:01:00Z },
{id: 3, date: 2015-08-18T00:02:00Z },
{id: 4, date: 2015-08-18T00:03:00Z },
{id: 5, date: 2015-08-18T00:04:00Z },
And I only want to get the records that are separated by at least 2 minutes.
record 2 would be invalid, because it is less than 2 minutes before record 1, but record 3 would be valid, so the result would be:
{id: 1, date: 2015-08-18T00:00:00Z },
{id: 3, date: 2015-08-18T00:02:00Z },
{id: 5, date: 2015-08-18T00:04:00Z },
I think the only way is to query them all, and do the filtering programmatically, but i am curious to know if there is an a pure mongoDB solution to this problem.

Related

Apollo graphql returning entire subdocument collection with each document

I'm working on a MERN stack with ApolloServer/Client. I wrote a query that should return Building documents (98 documents) with many subfields including an array of their associated Room subdocuments (1-9 subdocuments each, 379 total).
The query works great except that each Building document is being returned with an array of all 379 Room subdocuments.
I think I've narrowed it down to an issue with ApolloServer. I've confirmed the data in my MongoDB is correct and that the Mongoose call in the resolver returns the correct data. When I run the query to the frontend or in Apollo playground, I get the extra documents.
Here are some paraphrased example code
// MongoDB example
// buildings
{ "_id": 1, "address": "123 main st", "rooms": [{"_id": 12},{"_id": 15}]},
{ "_id": 2, "address": "125 main st", "rooms": [{"_id": 11}, {"_id": 16}, {"_id": 13}]},
{ "_id": 3, "address": "222 state st", "rooms": [{"_id": 14}]}
// rooms
{ "_id": 11, "number": "b7"},
{ "_id": 12, "number": "145"},
{ "_id": 13, "number": "12"},
// etc...
// Query
const resolvers = {
Query: {
Buildings: ()=> await Buildings.find({}).populate('rooms') // this returns correctly
}
}
// Typedefs
type Building {
_id: ID!
address: String!
rooms: [Room]
}
type Room {
_id: ID!
number: String!
}
query {
Buildings: [Building]
}
/* Something about this is returning
{[
{_id: 1, address: whatever, rooms: [11, 12, 13, 14, 15, 16]},
{_id: 2, address: whatever, rooms: [11, 12, 13, 14, 15, 16]},
{_id: 3, address: whatever, rooms: [11, 12, 13, 14, 15, 16]}
]}
instead of
{[
{_id: 1, address: whatever, rooms: [ 12, 15, ]},
{_id: 2, address: whatever, rooms: [ 11, 13, 16 ]},
{_id: 3, address: whatever, rooms: [ 14 ]}
]}
I'm working in a sizable code base. I've searched for any duplicated name functions in the typedefs like 'buildings' and 'rooms', but haven't found any. Suggestions?
Thanks!
You say that await Buildings.find({}).populate('rooms') returns the correct results.
I suspect that there is a type resolver for Building/rooms that has an incorrect query tied to it. Your typeDefs are fine, this is going to be in your resolvers code somewhere.
Ideally your Buildings query should just return [Building] then the resolver for the rooms field under Building should go figure out what rooms belong to a particular building and return [Room]

How to query algolia data with in the array of object

I have a data array with multiple objects in Algolia index as below.
[
{
status:available
startDate: 2000-10-20
endDate:2022-10-20
availablePlatform:[1,2,3]
availableCountry:908,
},
{
status:available,
startDate: 2023-10-20
endDate:2123-10-20
availablePlatform:[4,5,6,7]
AvailableCountry:[144],
},
]
I need to perform a filtering which should do a exact match within these objects.
Ex:
(1)
avails.status:available AND avails.availablePlatform:2 AND avails.availableCountry:908
This returns true as expected.
(2)
avails.status:available AND avails.availablePlatform:2 AND avails.availableCountry:144
This one also returns true as Algolia has matched availableCountry from the second object.
But i need to return false in this scenario. Does such a capability exist?, or are there other ways of approaching this problem that folks could point me to?
Same question asked here as well https://discourse.algolia.com/t/filtering-which-should-do-a-exact-match-within-data-objects-in-an-array/16677
Thanks.
According to this post on the Algolia discourse you will have to index a separate record for each element in the avails array and that this is the only way.
assuming your entry looks something like this
[{
objectID: 'someid',
somefield: 'somevalue',
avails: [{
status: 'available'
startDate: '2000 - 10 - 20'
endDate: '2022 - 10 - 20'
availablePlatform: [1, 2, 3]
availableCountry: 908,
},
{
status: 'available',
startDate: '2023 - 10 - 20'
endDate: '2123 - 10 - 20'
availablePlatform: [4, 5, 6, 7]
availableCountry: [144],
},
]
}]
you might have to break your entry to subentries on the index for each entry in the avails array. The downside of this is that now you will have increased number of records and redundant data for each element in the avails array
[{
objectID: 'someid-1',
somefield: 'somevalue',
avails: {
status: 'available'
startDate: '2000 - 10 - 20'
endDate: '2022 - 10 - 20'
availablePlatform: [1, 2, 3]
availableCountry: 908,
}
},
{
objectID: 'someid-2',
somefield: 'somevalue',
avails: {
status: 'available',
startDate: '2023 - 10 - 20'
endDate: '2123 - 10 - 20'
availablePlatform: [4, 5, 6, 7]
availableCountry: [144],
}
}
]

MongoDB query to show a column within an array

I wanted to display the grade and date from the database provided to me which is lists of restaurants within New York and its boroughs. I can show the grades but when I try to show the dates that are greater than 2012, I'm having trouble.
Here's the query that I used:
db.restaurants.find(
{
'grades.0.grade': 'A',
'grades.1.grade': 'A',
'grades.2.grade': 'A',
'grades.0.date': { $gt: 2013 },
},
{ borough: 1, cuisine: 1, name: 1, grades: 1, 'grades.grade': 1 }
);
How do I show them in a query?
EDIT: Here's the value within one cell of the date column: "2014-04-21T00:00:00.000+0000".

mongodb: order and limit the collection, then order and limit the resulting document nested documents

I have the following data structure on my game collection:
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}, {
id: 2,
created: 2010-10-10 00:00:30
}]
},
{
name: game2
date: 2010-10-09
media: [{
id: 1,
created: 2010-10-09 00:10:40
}, {
id: 2,
created: 2010-10-09 09:01:00
}]
}
I want to get the game with the highest date, then get the related media with the highest created to get it's id. In the example above, the result would be
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}]
}
I tried to use the find and find_one, and also aggregation, but I could not figure a way to make this query.
Any suggestions?
You will need to $unwind the media array in order to get the subdocument in that array where created is the highest then you $sort your documents by date and created all in descending order. Use $limit to output n documents which is 1 in our case.
In [26]: import pymongo
In [27]: conn = pymongo.MongoClient()
In [28]: db = conn.test
In [29]: col = db.gamers
In [30]: list(col.aggregate([{"$unwind": "$media"}, {"$sort": {"date": -1, "media.created": -1}}, {"$limit": 1}]))
Out[30]:
[{'_id': ObjectId('553323ec0acf450bc6b7438c'),
'date': '2010-10-10',
'media': {'created': '2010-10-10 00:00:59', 'id': 1},
'name': 'game1'
}]

Manipulating data in a complex mongoDB data model

{
name: “Bimal”,
role: “developer”,
reports_to: “girish”,
technology:[{
name: “PHP”,
rating: 5
},{
name: “JavaScript”,
rating: 4
}],
project: [{
project_name: “TGT”,
client_name: “Said”,
estimated_time: 20,
tasks: [{
start_time: new Date(2013, 2, 13, 7, 47),
end_time: new Date(2013, 2, 15, 7, 47),
Description: “design the page”
}, {
start_time: new Date(2013, 3, 13, 7, 47),
end_time: new Date(2013, 2, 13, 7, 47),
Description: “coding the page”
}]
}]
}
I have this complex database structure. Now I need to add a new technology and a rating to it after JavaScript.Also I need to edit the description of the task which has a a description "design the page".
To add a new Technology use either $push or $addToSet. To update the description in the Project section use the positional operator $ with $set . Remember in subdocument order is not maintain all the time . So In case you want the order in the technology key , please add one more key called Order and use it in each subdocument . While showing on the client side you can order it .
I removed my second query . One of the way if you wish to do even with limitation is that you can pull the data in the client side and then update the document and save it back , but there is no direct command to do so , you have to loop in client side
db.Collection.update({"name" : "Bimal"} , { "technology" : { $addToSet : { name: “New Technology”,rating: 1}}})
If possible and if you are OK , you can re structure you document like this
{tasks : [{ "ProjectName: "" , startDate : "" , EndDate : "" , Description : "" } ]
I know it will duplicate the data many times but this will one of the way that you can update any fields in the tasks sub document.