When fetching assets from the user's photo library, you must specify how you want the photos to be sorted. You do this by passing in a NSSortDescriptor(). There are a few completions, but I'm wondering if there's any way to pass in a "random sort".
I'm hoping there's something similar to the .sort function used like this:
var arr = [1, 2, 3]
arr = arr.sorted { Bool.random() } // Returns the array, sorted randomly
Is there any way I can achieve a "random sort" with NSSortDescriptor() ?
If not, is there any way to fetch random photos from a user's library (without fetching all of them and then sorting on those randomly) ?
I think you need to use a comporator in NSSortDescriptor for flexible sorting:
How to create an NSSortDescriptor using the comparator signature?
Related
I am working on a function that helps me find similar documents, sorted by score, using the full-text search feature of MongoDB Atlas.
I set my collection index as "dynamic".
I am looking for similarities in text fields, such as "name" or "description", but I also want to look in another field, "thematic", that stores integer values (ids) of thematics.
Example:
Let say that I have a reference document as follows:
{
name: "test",
description: "It's a glorious day!",
thematic: [9, 3, 2, 33]
}
I want my search to match these int in the thematic field and include their weight in the score calculation.
For instance, if I compare my reference document with :
{
name: "test2",
description: "It's a glorious night!",
thematic: [9, 3, 6, 22]
}
I want to increase the score since the thematic field shares the 9 and 3 values with the reference document.
Question:
What search operator should I use to achieve this? I can input array of strings as queries with a text operator but I don't know how to proceed with integers.
Should I go for another approach? Like splitting the array to compare into several compound.should.term queries?
Edit:
After a fair amount of search, I found this here and here:
Atlas Search cannot index numeric or date values if they are part of an array.
Before I consider to change the whole data structure of my objects, I wanted to make sure that there is no workaround.
For instance, could it be done with custom analyzers?
I solved it by adding a trigger to my collection. Each time a document is inserted or updated, I update the thematic and other similar fields counterparts, e.g. _thematic, where I store the string value of the integers. I then use this _thematic field for search.
Here is a sample code demonstrating it:
exports = function (changeEvent) {
const fullDocument = changeEvent.fullDocument;
const format = (itemSet) => {
let rst = [];
Object.keys(itemSet).forEach(item => rst.push(itemSet[item].toString()));
return rst;
};
let setter = {
_thematic: fullDocument.thematic ? format(fullDocument.thematic) : [],
};
const docId = changeEvent.documentKey._id;
const collection = context.services.get("my-cluster").db("dev").collection("projects");
const doc = collection.findOneAndUpdate({ _id: docId },
{ $set: setter });
return;
};
I'm pretty sure it can be done in a cleaner way, so if someone post it, I'll switch the selected answer to her/his.
Another way to solve this is to make a custom analyser with character mapping that will replace each digit with its string counterpart. I haven’t tried this one tho. See https://docs.atlas.mongodb.com/reference/atlas-search/analyzers/custom/#mapping
Alternatives welcome!
I have document structure like this in my schools collection
I am searching school by its code from array of codes School.findOne({ 'codes.code': '12345678' }) and I am getting my school but I also want to get code.type property from code object where my code is 12345678. Should i use javascript Array.find?
What you can do is selecting the matching array element by
School.find({ 'codes.code': '12345678' }, {"codes.$":1})
Otherwise, yes, you need to find the element in the array:
var myschool = School.find({ 'codes.code': '12345678' })[0]
myschool.codes.find(c => c.code == '12345678')
I have a local collection that logs when a user has viewed an entry. It stores the ID of the entry and the time it was viewed:
viewedDate = new Date();
notifications.insert({
'viewed': this.data._id,
'viewedDate': viewedDate
});
I want to exclude any of the 'viewed' ids in this collection from another find() (I basically want to count how many entries haven't been viewed)
How can I use the results of a notifications.find() to exclude results from another find()? If I assign the notifications.find() to a variable, it returns all kinds of stuff as an object.
edit
OK, so if I use fetch() I can restrict what comes back - can I do something with this in a find()?
myNotes = notifications.find({}, {fields: {'viewedDate' :0, _id:0}}).fetch();
This returns
[
Object
viewed: "HqYcCma3qKseHALyv"
__proto__: Object
]
Thanks to some invaluable help from garilla_ in the Meteor IRC, I got it working, solution as follows:
myViewedOffers = notifications.find({},{fields: {'viewed':1}}).fetch();
myViewedArray = myViewedOffers.map(function(viewed){return viewed.viewed});
offerCount = Offers.find({_id: {$nin: myViewedArray}}).count();
I have two fields with separate arrays that have comparable data in them.
The first has a Name, and an ID. The second has a nickname.
I want to make sure that the count of the two are the same. If they are not the same, I want to know the mongoID of that document.
How would I do this?
With MapReduce it would be possible. If your document looks like:
document: { array1: [ a, b], array2: [c] }
You could write map and reduce functions like:
map = function(){
if(this.array1.length!=this.array2.length)
emit(this_id,1);
}
reduce = function(key,values){ return key;}
For instance, to get the results inline:
db.foo.mapReduce(map,reduce,{out:{inline:1}}).results
Anyone have guidance on how to query an array of hashes in coffeescript?
For example, I have an array of hashes, each with a "name" and "setting":
[
{"name":"color", "setting":"red"},
{"name":"scale_min", "setting":"15"},
{"name":"scale_type", "setting":"linear"},
{"name":"x_axis_label", "setting":"Weeks"}
]
I want to find the element in this array where the hash "name" is "x_axis_label"
How can I easily do that with coffeescript?
I need some kind of value_for_key_in_object(key, object) function and figured if would be part of the lexicon...
I just hacked this up quickly:
data = [{"name":"color","setting":"red"},{"name":"scale_min","setting":"15"},{"name":"scale_type","setting":"linear"},{"name":"x_axis_label","setting":"Weeks"}]
find = (i for i in data when i.name is 'x_axis_label')[0]
alert(find.setting)
Demo
If you going to do this repeatedly, always looking for things where the name equals something, then you are better off converting this from an array of maps to just a map where the key is the name.
data = [
{"name":"color","setting":"red"}
{"name":"scale_min","setting":"15"}
{"name":"scale_type","setting":"linear"}
{"name":"x_axis_label","setting":"Weeks"}
]
myMap = {}
for row in data
myMap[row.name] = row.setting
alert(myMap['x_axis_label'])
Demo
I always prefer a 'multi language' solution over a 'idiomatic' solution. Thus you can to use Array.filter
data = [{"name":"color","setting":"red"},{"name":"scale_min","setting":"15"},{"name":"scale_type","setting":"linear"},{"name":"x_axis_label","setting":"Weeks"}]
find = (data.filter (i) -> i.name is 'x_axis_label')[0]
alert find.setting
If you happen to be using Underscore.js, you can use find:
xAxisLabel = _.find data, (datum) -> datum.name is 'x_axis_label'