How to sort this array of results? - mongodb

Here is my query that attempts to sort an array of MongoDB documents based on a derived field called expiresAt. expiresAt is a Date object that represents the date string stored in doc.expirationDate.
It fails with an error TypeError: ... .sort({}) is not a function (shell):5
db.tokens.find().map(function(doc) {
var expiryDate = new Date(doc.credentialsMap.linkedin.expirationDate);
doc.expiresAt = expiryDate;
return doc;
}).sort({'expiresAt': -1});
What am I doing wrong? It's unclear to me exactly what return type map provides. If it's a cursor then why isn't sort supported? It's clearly available in the docs.

cursor.map() returns a Java script array.
The way you're calling sort() assumes that the return value is a MongoDB cursor, that's why it fails.
You'd have to use the regular Array.sort syntax.
For example, to have your map results sorted in descending order, use the following:
db.tokens.find().map(function(doc) {
var expiryDate = new Date(doc.credentialsMap.linkedin.expirationDate);
doc.expiresAt = expiryDate;
return doc;
}).sort(function(a,b) { return b.expiresAt - a.expiresAt});

Related

Looping Over a Java Object and Passing One Field to a Mongo Query Similar to SQL WHERE...IN Clause

I am trying to construct a MongoDB equivalent of an SQL WHERE IN clause by iterating over a Java Object List and using one field in that list to fill in the IN data. Using generic example, I would like to build the following command in MongoDB syntax:
SELECT title FROM albums WHERE recorded_year IN ('1967','1968','1969','1970');
The SQL command IN data is extracted from the Album object recordedYear value using the following loop:
if (albums.size() <= 1000) {
sb.append("SELECT title FROM albums WHERE recorded_year");
sb.append(" IN (");
for (int i = 0; i < albums.size(); i++) {
sb.append("'");
sb.append(albums.get(i).getRecordedYear());
sb.append("'");
if (i < albums.size() - 1) {
sb.append(",");
} else {
sb.append(")");
}
}
}
Most Mongo/Java sites I visited seem to deal with command structures using hard-coded values which, while helpful, is completely impractical in real world applications. Any help in pointing to a good tutorial, or if someone has the actual code itself would be greatly appreciated.
Thanks.
But the issue I am having is understanding how to pass a Java Object
list to the to the getAllDocuments...
Make an array of elements which you want to match with the field using the in operator. For example, If you have a someObject.year field, then the array will have the year values; int [] matchYears = { 1989, 2001, 2012 }. Instead of an array you can also use a List collection.
The query:
Bson queryFilter = in("recordedYear", matchYears);
List<Document> result = new ArrayList<>();
collection.find(queryFilter).into(result);
result.forEach(System.out::println);
The queryFilter is built using the com.mongodb.client.model.Filters factory class.
The MongoDB documentation on using the $in operator.
NOTE: The int [] matchYears = { 1989, 2001, 2012 } can be also be created as
int [] matchYears = { javaObject1.recorded_year, javaObject2.recorded_year, ... }.
I didn't quite implement it with BSON, but the logic in the method appears to be working with the code below. Thank you again for your help.
public void getAlbumYears(MongoCollection<Document> collection, List<Album> albums) {
BasicDBObject inQuery = new BasicDBObject();
List<String> year = new ArrayList<>();
for(Album album : albums) {
year.add(album.getYear());
}
inQuery.put("year", new BasicDBObject("$in", year));
for (Document document : collection.find(inQuery)) {
System.out.println(document.toJson());
}
}

How can I project date string or object instead of date number field in mongodb find query?

I have a date field that is javascript number date and I want to get the string or object of date (like new Date(date)) in find query projection instead of date field itself that is number.
//I want to get
datetime:new Date(date)
//instead of
db.myCollection.find({},{date:1})
thanks.
You can use forEach or map function
db.yourCollectionName.find({}).map(function(doc) {
return {
d:new Date(doc.datetime)
};
});

Deleting a document from a mongodb collection

I have a collection called customers and it contains documents.
I have written a function to delete a document using the field and its value which takes as arguments.
But it doesn't remove any customer as expected. Can anybody show me where I have gone wrong?
function (fieldName, value) {
db.customers.remove({x : y});
}
I called the function from the mongo terminal as below.
db.loadServerScripts();
removeDocument("firstName", "Sam");
Thanks
Rewrite your function so that the arguments become part of the query object. You can do this using either computed property or bracket notation.
Using computed property:
function removeDocument(fieldName, value) {
db.customers.remove({[fieldName]: value});
}
Using bracket notation
function removeDocument(fieldName, value) {
var query = {};
query[fieldName] = value;
db.customers.remove(query);
}
db.collection.remove is deprecated so use deleteOne or deleteMany(For deleting multiple documents)

How to specify key-value pairs

First, let me say that I am a novice so may not ask this question as clearly as it could have been asked. here goes
From java I am calling a function FindName(int,string) (snippet below), I am getting the JSONParser errors on the DBObject ref statement. The code works fine if I hardcode the value pairs, but the goal is for the calling routine to pass different values and get the correct result.
The values being passed are valid, I even println to verify the values.
The issue seems to be that even though the values are valid int and string that mongodb does not seem to allow you to specify the names of the values that are passed to this function in the key-value pairs.
Therefore I am guessing that you need to transform the date, name values that are passed in, to a format that is acceptable to the key-value pair. The question is how to do that.
static String FindName(int date, String name)
MongoClient mongoClient;
try {
mongoClient = new MongoClient("xxx.xx.xx.xxx",27017);
}
catch (UnknownHostException e)
{
e.printStackTrace();
return name;
}
DB db = mongoClient.getDB("tpfdf");
DBCollection PNR = db.getCollection("PNR");
DBObject ref = (DBObject) JSON.parse("{PnrByDateFlightCustom: {date: date), pname: name'}}");
at com.mongodb.util.JSONParser.parse(JSON.java:208)
at com.mongodb.util.JSONParser.parseObject(JSON.java:241)
at com.mongodb.util.JSONParser.parse(JSON.java:205)
at com.mongodb.util.JSONParser.parseObject(JSON.java:241)
at com.mongodb.util.JSONParser.parse(JSON.java:205)
at com.mongodb.util.JSONParser.parse(JSON.java:155)
at com.mongodb.util.JSON.parse(JSON.java:93)
at com.mongodb.util.JSON.parse(JSON.java:74)
at MongoDB5.locatePassengerName(MongoDB5.java:38)
at MongoDB5.main(MongoDB5.java:11)
Update. After many trial and errors, I found that if you dynamically build the string and then execute the ref with the dynamic string, it works.
This worked. I do not know if this is the correct way to code this, but this works so will go with it for now.
String mdbStr = "{PnrByDateCustom: {date:" + value + "}}";
System.out.println("mdbStr = " + mdbStr);
DB db = mongoClient.getDB("tpfdf");
DBCollection PNR = db.getCollection("PNR");
DBObject ref = (DBObject) JSON.parse("{}");
// ref = (DBObject) JSON.parse("{PnrByDateCustom: {date: value} }" );
ref = (DBObject) JSON.parse(mdbStr);

Most efficient way to return document with highest DateTime value in field

I have a lucene's index with documents - all of them contain field that stores DateTime value. What would be recommended/most efficient way to extract document with highest value. How it would look like for integer values? Of course i am assuming that values are converted to string using DateTools.DateToString or similar methods.
Elaborating on Jf Beaulac answer, an example of such code may look like the one below. Please note that 'CreatedAt' field is used to store DateTime values.
//providing query that will not filter any documents
var query = new TermRangeQuery("CreatedAt", DateTools.DateToString(DateTime.MinValue, DateTools.Resolution.MINUTE), DateTools.DateToString(DateTime.MaxValue, DateTools.Resolution.MINUTE), false, false);
//providing sorting on 'CreatedAt' and returning just one result
var createdAtSerchResults = searcher.Search(query, null, 1, new Sort(new SortField("CreatedAt", SortField.LONG, true)));
//extracting CreatedAt value from returned document
var documentWithMaxCreatedAt = searcher.Doc(createdAtSerchResults.ScoreDocs.First().Doc);
var result = DateTools.StringToDate(documentWithMaxCreatedAt.Get("CreatedAt"));
Just issue a Query with a Sort descending on your field that contains the Date.
Use a Search method that takes a Sort in parameter, like this one:
IndexSearcher.Search(Query, Filter, int, Sort)