How to create a compound index in MongoDB through Java driver? - java

I want to create compound index on Age and Name in MongoDB through Java driver and here is my syntax:
coll.ensureIndex(new BasicDBObject("Age", 1),new BasicDBObject("Name", -1));
List <DBObject> list = coll.getIndexInfo();
for (DBObject o : list) {
System.out.println(o);
}
but it create only 1 index not compund index and give me result this:
{ "v" : 1 , "key" : { "_id" : 1} ,"ns" :"EmployeeData.EmpPersonalData", "name":"_id_"}
{ "v" : 1 , "key" : { "Age" : 1} , "ns" : "EmployeeData.EmpPersonalData" , "name" : "Age_1" , "Name" : -1}
So how can compund index on collection can be created through java driver?

If you look at your code, you have actually called ensureIndex with two parameters. Your first parameter was the key and your second parameter became some extra field: Name: -1.
What you are looking to pass in the first parameter is this object {"Age":1, "Name":-1}. What you actually passed was {"Age":1}, {"Name":-1}.
So you want to do something like this:
BasicDBObject obj = new BasicDBObject();
obj.put("Age", 1);
obj.put("Name", -1);
coll.ensureIndex(obj);
Note that the index will be created with a default name. To provide a specific name do the following:
coll.ensureIndex(obj, "MyName");

You can try this according to the official documentation.
import org.bson.Document;
db.getCollection("restaurants").createIndex(new Document("cuisine", 1).append("address.zipcode", -1));
Official Mongo DB Driver Java documentation

A more modern and perhaps fluent approach could be:
import com.mongodb.client.model.Indexes;
collection
.createIndex(
Indexes.compoundIndex(
Indexes.ascending("Age"),
Indexes.descending("Name")
)
);
Found in the manual. Formatted for clarity; post-format to your own taste.

Related

Update/add a single value to an array in MongoDB - but not as list?

I want to simply add one value to a tuple from MongoDB.
The key is query, and the variable position should be added as consumer-Variable in the tuple with the following code:
MongoCollection<Document> collection = ...
Bson filter = Filters.eq("query", queryName);
Bson update = Updates.addToSet("consumer", position);
collection.findOneAndUpdate(filter, update);
However, when I look into my database, it looks like a list "consumer" : [ NumberLong(88760) ] has been inserted and not a single value, as shown in the producer field:
{ "_id" : ObjectId(...), "query" : "1000", "consumer" : [ NumberLong(88760) ], "producer" : NumberLong(88760) }
I also tried Update.push() with the same result.
How can I add just a single value, without having it as list?
For example, if you need to update only 1 object from the list inside, you can do it in the format as:
.update_one({"_id": ObjectId(_id)}, {"$set": {"i.5": list[2]}})
where "i.5" - 5 index of the list i.

Check if a value exists in an array, MongoDB bind projection using spring data

I have a more complex aggregation query when I try to bind my result using projections, I need to check that Array contains a date (day).
MongoDB query works fine
{ "$project" : { "days" : { "day" : "$_id" , "signatureVerified" : {"$in": ["$_id", "$signatureVerified"] } }}}
spring-data-code
project().and(DAYS).nested(bind(DAY, _ID)and(Field field));
I've tried preparing a match array checker using an ArrayOperators class but there is no possibility to return a Field object. Any ideas on how it can be achieved?
ArrayOperators.arrayOf(SIGNATURE_VERIFIED).containsValue(Fields.field(_ID));

update map directly in mongoDB

I have a collection in mongoDB and its documents have 3 fields like below:
{
"_id" : { "$oid" : "5396ad5de4b09ea27a641ed6"} ,
"word" : "test_word" ,
"doc_occurrence" : "'total':25,'sport':10" ,
"total_occurrence" : "'total':32,'sport':15"
}
I want to know can I update value of the key directly using java (using dot for example)? or I have to get map completely and update this way?
If i have to use sub-document to update values through dot notation,what type of data type I must use to keep sub-doument fields?
p.s: above collection structure is what is printed in java.
collection structure in mongo terminal is like this:
{
"_id" : ObjectId("5396d751e4b0cabeab49be0b"),
"word" : "test_word",
"doc_occurrence" : { "total" : 25, "sport" : 10 },
"total_occurrence" : { "total" : 32, "sport" : 15 }
}
These you can update a single field by the following:
BasicDBObject query = new BasicDBObject(
"_id", new ObjectId("5396ad5de4b09ea27a641ed6")
);
BasicDBObject update = new BasicDBObject(
"$set", new BasicDBObject("doc_occurance.total", 30)
);
table.update(query,update);
So this uses the $set operator and the use of "dot notation" to indentify and singularly update an element in a sub-document. You can specify as many fields as you need within the $set operator part of the update.
I assume you're looking for findAndModify. This question more or less treats your problem: MongoDb's $set equivalent in its java Driver.
I am also not sure about the structure of your document ... maybe you forgot a few { } at the doc_occurrence and total_occurrence.

How to find a document and update its list in mongoDB with java drivers?

I want to find a document by some values in objects from one list and update that list object values.
While it finds the document by the list values and subtracts the value of topups.total.cnt and topups.total.revenue (if it didn't then they would be 3 and 36000000), it doesn't change the false to true except for the first object
in the list.
I think this line
"updateObj.append("$set", new BasicDBObject("topups.data.$.isRb", true))"
is the problem. It doesn't update the the object that the myQuery defines.
The below false should all be true after running the code three times.
"topups" : {
"data" : [
{
"val" : 12000000,
"chId" : 2,
"reqSys" : "222220002899",
"old" : NumberLong(189398),
"isRb" : true
},
{
"val" : 12000000,
"chId" : 2,
"reqSys" : "222220002899",
"old" : NumberLong(189398),
"isRb" : false
},
{
"val" : 12000000,
"chId" : 2,
"reqSys" : "222220002899",
"old" : NumberLong(189398),
"isRb" : false
}
],
"total" : {
"cnt" : 0,
"revenue" : 0
}
},
This is the code..
BasicDBObject myQuery = new BasicDBObject();
myQuery.append("d", new BasicDBObject("$gte", dayOfYear - 2).append("$lte", dayOfYear))
.append("m", msisdn)
.append("topups.data.reqSys", reqSystem)
.append("topups.data.isRb", false)
.append("topups.data.chId", 2)
.append("topups.data.old", preEventBalance)
.append("topups.data.val", callCost);
BasicDBObject updateObj = new BasicDBObject();
updateObj.append("$set", new BasicDBObject("topups.data.$.isRb", true))
.append("$inc", new BasicDBObject("topups.total.revenue", -callCost)
.append("topups.total.cnt", -1));
mongoDBcollection.update(myQuery, updateObj);
This looks like the same question as this: How to Update Multiple Array Elements in mongodb
The answer, sadly, being that you cannot, in a single operation, update all documents in an array.
I think you are looking for something like this,
http://docs.mongodb.org/manual/reference/method/db.collection.update/#update-a-document-element
The document (for 2.4 ) says that it will only update the first element of an array. So I guess can't be done using the $ operator.
You can try and do it either by updating individual element, like "topups.data.1.isRb" : true or Create an array outside with updated values and replace the entire array.
Hope this helps.
I don't want to update all the records at once (as the above ticket from dex mentions or the link for the question Trisha mentions). I want to update one at a time.
So, if the code above runs one time (and all "isRb" is false), all three list members match "myQuery" so I want one of three to be changed to "true" (not all three).
Second time the code runs, two list members match "myQuery" so I want one of two to be changed to "true" (not all two).
Third time the code runs, only one list member matches "myQuery" so I want that one to be changed to "true" (after all it is the only one left "false" after two runs).

Parsing strings to mongodb query documents with operators in java

In a project I'm working on, at one point I read a query to mongodb from a string. I've been using com.mongodb.util.JSON.parse(querystring) to read the query, which worked fine until I started reading queries that contained operators like $max and $min. At that point, rather than using mongodb's $max operator, the parser instead creates a "$max" field. For instance,
the input string:
{ $query : { state : "AL" } , $max : { pop : 9058 } }
is parsed to the DBObject:
{ "$query" : { "state" : "AL"} , "$max" : { "pop" : 9058}}
When I then look for a DBCursor with that query document, I get a cursor of size 0 (no matching document found in the databse), presumably because there are no documents with "$query" or "$max" fields.
Is there something I can use besides JSON.parse()? I'm not averse to writing my own function for it, but how can I get a DBObject that recognizes the $ operators as operators and not fields?
Any advice would be appreciated!
The following code snippet using query modification operator $max seems to work fine.
/* {$query:{state:"AL"}, "$max":{pop:10000}}*/
String s = "{$query:{state:\"AL\"}, \"$max\":{pop:10000}}";
DBObject dbObject = (DBObject) JSON.parse(s);
System.out.println("\nFind all: ");
DBCursor cursor = collection.find(dbObject);
try {
while (cursor.hasNext()) {
DBObject cur = cursor.next();
System.out.println(cur);
}
} finally {
cursor.close();
}
Make sure you have specified index on pop.
db.zips.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "test.zips",
"name" : "id"
},
{
"v" : 1,
"key" : {
"pop" : 1
},
"ns" : "test.zips",
"name" : "pop_1"
}
]
See the following link for detail.
http://docs.mongodb.org/manual/reference/operator/max/
Just in case you are interested in using aggregation operators $max or $min, the following link provide details and sample code.
http://docs.mongodb.org/ecosystem/tutorial/use-aggregation-framework-with-java-driver/
So it turns out the DBObject as given up there worked out fine. It returns a cursor with a size of 0, true, but the DBCursor's length is actually the thing I was looking for. (Previously, I had been checking whether the cursor's size was 0, and if it was, returning null.)
I'm not quite sure what the difference between size and length is in a DBCursor (the difference between size and count is apparent, but I'm not sure what length is supposed to be), but it works now. In the case above, size and count were both 0 but length was the desired number.

Categories