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],
}
}
]
Related
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".
I started learning MongoDB a few days ago and trying to wrap my head around update operator.
Here's the document structure I have:
db.records.insertMany([
{
name: 'first',
subrecords: [
{ id: 1, isToBeUpdated: 0, value: 1 },
{ id: 2, isToBeUpdated: 0, value: 2 },
{ id: 3, isToBeUpdated: 0, value: 3 },
{ id: 4, isToBeUpdated: 1, value: 4 }
]
},
{
name: 'second',
subrecords: [
{ id: 22, isToBeUpdated: 1, value: 5 },
{ id: 23, isToBeUpdated: 0, value: 6 },
{ id: 24, isToBeUpdated: 1, value: 7 },
{ id: 25, isToBeUpdated: 0, value: 8 }
]
}
])
I'm writing a command that is supposed to update subrecords.
My intent is to use isToBeUpdated flag — if it is set to 1 we update the value field, e.g. multiplying it by 10. We ignore items with isToBeUpdated being 0.
Here's the command I've composed:
db.records.update(
{ 'subrecords.isToBeUpdated': 1 },
{ '$mul': { 'subrecords.$.value': 10 } },
{ multi: true }
)
I expect to get the following items of subrecords array updated like this:
1. { id: 4, isToBeUpdated: 1, value: 40 }
2. { id: 22, isToBeUpdated: 1, value: 50 }
3. { id: 24, isToBeUpdated: 1, value: 70 }
BUT it just updates 2 records, instead of 3. The following record is not updated:
3. { id: 24, isToBeUpdated: 1, value: 70 }
It is the second item with isToBeUpdated being 1 located in the second document's subrecords collection — seems like the query only updates the first matching item of subrecords array in any document. And ignores other records that are subsequent to first.
I tried tweaking my command adding [] to $ (positional operator):
... { '$mul': { 'subrecords.$[].value': 10 } }, ...
But in this case literally every single item in subrecords array of any document gets affected.
Anyone knows how to write a command which loops through all records and updates each item of the nested subrecords array with isToBeUpdated field being set to 1?
Also, am I right in thinking
that { multi: true } implies that ALL record documents in records collection will be affected?
that { 'subrecords.isToBeUpdated': 1 } (query part) literally means that WE ONLY UPDATE subrecords ARRAY WHEN A DOCUMENT HAS AT LEAST ONE ITEM IN subrecords ARRAY WITH isToBeUpdated FIELD BEING SET TO 1?
The workaround turns out to be arrayFilters
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#update-all-documents-that-match-arrayfilters-in-an-array
The $[<identifier>] operator facilitates updates to arrays that contain embedded documents. To access the fields in the embedded documents, use the dot notation on the $[<identifier>].
db.records.update(
{},
{ '$mul': { 'subrecords.$[elem].value': 10 } },
{
multi: true,
arrayFilters: [{ 'elem.isToBeUpdated': 1 }]
}
)
Solved!
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.
Good day. I have the following documents.
{
id: 1,
status: "sleeping"
}
{
id: 2,
status: "eating"
},
{
id: 3,
status: "drinking"
},
{
id: 4,
status: "drinking"
},
{
id: 5,
status: "sleeping"
},
{
id: 6,
status: "studying"
},
...
How do I sort them by status with the following order? sleeping, drinking, eating, studying
I'm using Angular-Meteor. And I'm trying to publish a collection with a limit in the server since I'm dealing with a very large data set.
I was looking into aggregate which I think is the right solution for this case but Meteor doesn't support it.
Well, I ended up with attaching a number to sort the the documents in the following order: sleeping, drinking, eating, studying
{
id: 1,
status: "sleeping",
statusOrder: 0
}
{
id: 2,
status: "eating",
statusOrder: 2
},
{
id: 3,
status: "drinking",
statusOrder: 1
},
{
id: 4,
status: "drinking",
statusOrder: 1
},
{
id: 5,
status: "sleeping",
statusOrder: 0
},
{
id: 6,
status: "studying",
statusOrder: 3
},
...
It was easier, quite frankly.
But if you are interested with using MongoDB group for your app, I found something that might help. Link here.
The mongodb aggregation framework is available on the server side via the monbro:mongodb-mapreduce-aggregation package (for example). You can use this in your publication.
Another approach is to denormalize your data somewhat and include the sort key in each document. That involves a typical storage vs. speed tradeoff.
MongoDb just only support sort following A -> Z, Z -> A, 0 -> 9, 9 -> 0
Specify in the sort parameter the field or fields to sort by and a value of 1 or -1 to specify an ascending or descending sort respectively.
Example:
db.orders.find().sort( { "status": -1 } )
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'
}]