Mongo DB : Implementing $not query - mongodb

I am trying to implement following query from java code:
{ "Post Text" : { "$not" : /.*golf.*/i}}
my java code:
BasicDBObject not = new BasicDBObject();
not.append("$not", "/.*golf.*/i");
BasicDBObject query = new BasicDBObject();
query.put("Post Text", not);
When I am running above query, getting this log:
Cursor id=0, ns=journaldev.Rotunda, query={ "Post Text" : { "$not" : "/.golf./i" }}, numIterated=0, readPreference=primary
extra quotes around the regular expression are creating problem. Can someone help me in fixing this?

Using 3.x, you can use the Filters utility class to create various queries for you. In your case, you need the following construct:
Bson myFilter = Filters.not(
Filters.eq("Post Text",
Pattern.compile(".*golf.*", Pattern.CASE_INSENSITIVE)));
Using the 3.x driver to execute such a query is along the lines of:
MongoClient mongoClient = new MongoClient();
MongoCollection<Document> coll = mongoClient.getDatabase("test").getCollection("mycoll");
coll.find(myFilter); // do something with the FindIterable returned here

You can try something like this
Pattern textRegex = Pattern.compile(".*golf.*", Pattern.CASE_INSENSITIVE);
BasicDBObject not = new BasicDBObject("$not", textRegex);
BasicDBObject query = new BasicDBObject("Post Text", not);
When you pass a pattern, mongo driver automatically takes care of making it a regex. If you debug and see the code it will run with "$regex".
Hope this solves the problem

Related

Cursor error when using aggregation for MongoDB in Java driver

I want to aggregate by group, then sort and limit. Here's my code:
if(m!=null){
db = m.getDB("FMdb");
DBCollection collection = db.getCollection("user_artists");
DBObject group = new BasicDBObject("$group", new BasicDBObject("_id", "$artistID").append("total", new BasicDBObject("$sum", "$weight")));
DBObject sort = new BasicDBObject("$sort", new BasicDBObject("total", -1));
DBObject limit = new BasicDBObject("$limit", 1);
List<DBObject> pipeline = Arrays.asList(group,sort,limit);
AggregationOutput output = collection.aggregate(pipeline);
for (DBObject d : output.results()){System.out.println(d);}
}
Here is the error message from bash:
Exception in thread "main" com.mongodb.MongoCommandException: Command failed with error 9: 'The 'cursor' option is required, except for aggregate with the explain argument' on server 127.0.0.1:27017. The full response is { "ok" : 0.0, "errmsg" : "The 'cursor' option is required, except for aggregate with the explain argument", "code" : 9, "codeName" : "FailedToParse" }
So, I was not able to compile your code, not sure what the namespaces are, and you did not include them. Here is an example where every object is fully qualified. I think this is working as you want. I believe the objective is to find the artist having the most entries and provide the count of entries for that artist...
private static void Aggregate2(com.mongodb.client.MongoDatabase db) {
com.mongodb.client.MongoCollection<org.bson.Document> collection = db.getCollection("user_artists");
com.mongodb.client.AggregateIterable<org.bson.Document> aggregateIterable = collection.aggregate(java.util.Arrays.asList(
com.mongodb.client.model.Aggregates.group("$artistID", com.mongodb.client.model.Accumulators.sum("total", 1)),
new org.bson.Document("$sort", new org.bson.Document("total", -1)),
new org.bson.Document("$limit", 1)
));
for(org.bson.Document document : aggregateIterable) {
String json = document.toJson();
System.out.println(json);
}
}
I find many similar errors here and couldn't find a solution before. It turns out the code itself is fine. The problems is incompatibility of MongoDB and java-drive package.
My MongoDB version is v4.0.9.
My previous java-drive package was 3.0.0-beta1.
After updated the package to 3.8.0, my codes posted worked perfectly ever since.
If you confront similar errors, you can find the package here.
mongo-java-driver-3.8.0.jar

Will upsert work with array Elements as well as the normal ID in MongoDB through Java driver

Mongo DB contains the following data:
The requirement is if inside this document an Field exists incremnt the counter else insert the field.
Generally we use upsert for situations when we are not sure if its going to be insert or Update.But will this work with
array Elements as well
db.arrayexample.find()
{ "_id" : "userID", "addresses" : [ { "arrayid" : NumberLong(16694), "count" : 12 } ] }
My Java code is as follows:
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase mongoDatabase = mongoClient.getDatabase("testdb3");
MongoCollection mongoCollection = mongoDatabase.getCollection("arrayexample");
BasicDBObject query = new BasicDBObject();
query.put("_id", "userID");
query.put("addresses.arrayid",Long.valueOf(16695) );
mongoCollection.findOneAndUpdate(query,new Document("$inc", new Document("addresses.$.count", 1)),new FindOneAndUpdateOptions().upsert(true));
I am getting the following error when i run the Program:
'exception: Cannot apply the positional operator without a corresponding query field containing an array.' on server localhost:27017. The full response is
"value" : null, "errmsg" : "exception: Cannot apply the positional operator without a corresponding query field containing an array.", "code" : 16650,
Will $Upset work with array Elements as well as the normal ID
No, upserts will not work when using the $positional operator, as noted in the MongoDB documentation.
http://docs.mongodb.org/manual/reference/operator/update/positional/#upsert
Edit: As some flavour, it appears that there is an open feature request to support this particular kind of update when combined with the $setOnInsert operator within MongoDB's Jira https://jira.mongodb.org/browse/SERVER-10711

Mongo DB regex aggregation query using java API

I want to query using regex and aggregation in mongo db, the following is working fine in mongo shell but how to write the same using Java API.
db.posts_collection.aggregate({$unwind:"$posts"},
{$match :{"posts.message":/.*keyword.*/} })
I tried using the following but unable to get the required result,
BasicDBObject unwind = new BasicDBObject("$unwind","$posts");
BasicDBObject matchKeyWord = new BasicDBObject("$match",new
BasicDBObject("posts.message",java.util.regex.Pattern.compile("keyword")));
AggregationOutput output = collection.aggregate(unwind,matchKeyWord);
Please tell me how to write the same query in java.
I would think that should work, but if you really wanted to be sure use the $regex operator form instead:
BasicDBObject unwind = new BasicDBObject("$unwind","$posts");
BasicDBObject matchKeyWord = new BasicDBObject(
"$match",new BasicDBObject(
"posts.message",new BasicDBObject("$regex",".*keyword.*")
)
);
AggregationOutput output = collection.aggregate(unwind,matchKeyWord);
That operator exists for the purpose of "safe" serialization with differing drivers.

Grails Mongo Low Level API

What would be the equivalent of this line in groovy code when using the Mongo low level API?
db.countrycodes.findOne({"Country":"Antarctica"})
This line successfully finds the appropriate record for me in the Mongo shell but I tried many variations of it in my controller method and I keep getting NULL. Heres is my current attempt which is failing:
MongoClient mongoClient = new MongoClient("localhost", 27017)
DB db = mongoClient.getDB("twcdb");
DBCollection coll = db.getCollection('countrycodes')
println coll.find("Country":"Antarctica")
I know my collection and db is non NULL because when I do find() I do get a valid cursor back through which I can print the first record in collection. Here is the record I am trying to find:
{
"_id" : ObjectId("539848b2119918654e7e90b1"),
"Country" : "Antarctica",
"Alpha2" : "AQ",
"Aplha3" : "ATA",
"Numeric" : "10",
"FIPS" : "AY",
"IGA" : ""
}
Try this:
def cursor = coll.find()
def obj = cursor.next()
while (obj.Country != 'Antarctica') {
obj = cursor.next()
}
It is inefficient, you will have to traverse the whole collection everytime to find a record, but it will end up with 'obj' being the record you need.
Try below code and see if it works.
BasicDBObject query = new BasicDBObject("Country", "Antartica");
def cursor = coll.find(query)
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
For more info look here: http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/

How to build an $in query of ObjectIds using QueryBuilder with MongoDB

I am trying to build an $in query with QueryBuilder (MongoDB Java API 2.9.1). I have no problem when the query is an array of strings but when I try with an array of ObjectIds it doesn't work (returns nothing).
I am able to run the query successfully and get a result from the console:
Query in console:
db.collection.find({removed:false,app_id: {$in : [ObjectId("4f75c533ac99d845186e19b2"), ObjectId("4f75c533ac99d845186e19b3")]}})
Query created by QueryBuilder (MongoDB Java API 2.9.1):
Object[] ids;
Java code:
DBObject query = QueryBuilder.start("app_id").in(ids).and("removed").is(false).get();
ToString on DBObject produces:
{ "app_id" : { "$in" : [ { "$oid" : "4f75c533ac99d845186e19b2"}]} , "removed" : false}
Not sure if I am doing something wrong or the API doesn't support and $in query of type ObjectId. Any ideas?
Your ids should be of type org.bson.types.ObjectId so something like this should work:
import org.bson.types.ObjectId;
ObjectId[] ids = new ObjectId[]{
new ObjectId("1234568abcd"),
new ObjectId("1234567abcd")};
DBObject query = QueryBuilder.start("app_id").in(ids)
.and("removed").is(false).get();