How to query whole word in Java MongoDB - java

I'm using Java Mongo DB driver.
Im doing some OR and AND operation to query the collection.
QueryObj = new BasicDBObject("key1",Pattern.compile("v",Pattern.CASE_INSENSITIVE));
QueryList.add(QueryObj);
DBObject OrQuery = new BasicDBObject("$or", QueryList);
DBCursor cursor = MyCollection.find(OrQuery);
my Sample collection have 4 rows(JSON format might be wrong)
{
"key1": ["val1","val3"]
},
{
"key1": ["val2","val3"]
},
{
"key1": ["val3"]
},
{
"key1": ["val1","val2"]
}
If i search for "val2"
QueryObj = new BasicDBObject("key1",Pattern.compile("val2",Pattern.CASE_INSENSITIVE));
i'm getting expected output 2nd and 4th row
{
"key1": ["val2","val3"]
},
{
"key1": ["val1","val2"]
}
if i search just "v"
QueryObj = new BasicDBObject("key1",Pattern.compile("v",Pattern.CASE_INSENSITIVE));
i should get null set, but getting all the 4 rows, though the array have a character "v".
i need to search the whole word.

Do you mean that you want to search for the complete word 'v' -- in which case, I believe your pattern would be as follows where ^ denote the start of word and $ denote the end of word.
QueryObj = new BasicDBObject("key1",Pattern.compile("^v$",Pattern.CASE_INSENSITIVE));
Regards,
Kay

I hope it should help you
values ="val1";
CMD we use in DB as :
db.collection_name.findOne({ key1: "val1"})
Likewise use
query.put("key1", values)
Use the findOne() instead of find() in the statement
Correct me if 'm wrong

If you have the 4 documents above you can just use the following query to retrieve only the ones you need:
db.collection.find({"key1": "val2"})
This returns:
{ "_id" : ObjectId("507587fdf1ab6b3d9e0151d3"), "key1" : [ "val2", "val3" ] }
{ "_id" : ObjectId("50758801f1ab6b3d9e0151d5"), "key1" : [ "val1", "val2" ] }
(assuming your collection is called 'collection').
In the Java Driver the correct call should be:
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("test");
BasicDBObject query = new BasicDBObject("key1", "val2");
db.getCollection("collection").find(query);
//omitting try catch
If I understand your question correct, you don't need to use a Pattern here.
hope this helps

Related

MongoDB query for value in field with regex using Java

I am trying to query from my collection of documents which looks like:
{ "_id" : ObjectId("94"), "EmailAddress" :"adam#gmail.com","Interests": "CZ1001,CE2004" }
{ "_id" : ObjectId("44"), "EmailAddress" :"ben#gmail.com", "Interests":"CE1001,CE4002" }
{ "_id" : ObjectId("54"), "EmailAddress" :"chris#gmail.com","Interests":"CE1001,CE2002" }
An example is that i want to retrieve the email addresses, given that the field "Interests" has that value i am looking for.
Example if i search CZ1001, i will get back Obj 1 EmailAddress details.
If i search CE1001, i will get back Obj 2 and Obj 3 EmailAddress details.
The object id are uniquely created when i inserted records at the start if that helps.
I am able to get the objects on MongoDB Shell using
db.users.find(Module: {"$regex": "CE1001"}})
Only the email addresses are needed.
I am trying to get all the email addresses and got stuck at this code.
Document doc = (Document) collection.find(new BasicDBObject("Module", {"$regex":"CE1001"})) .projection(Projections.fields(Projections.include("EmailAddress"), Projections.excludeId())).first();
Where
new BasicDBObject("Module", {"$regex":"CE1001"}) is not allowed.
new BasicDBObject("Module", String_variable) is allowed
For a particular Interest, your mongoDB query would look like(taking CE1001 as an example):
db.collection.find({
$or: [
{
Interests: {
$regex: "^CE1001,"
}
},
{
Interests: {
$regex: ",CE1001,"
}
},
{
Interests: {
$regex: ",CE1001$"
}
}
]
},
{
"EmailAddress": 1
})
For others who happens to drop by this post. Below are the working codes. Credits to #Veeram.
FindIterable <Document> results = collection.find(new BasicDBObject("Module", new BasicDBObject("$regex", "CE1001")) .projection(Projections.fields(Projections.include("EmailAddress"), Projections.excludeId()));
for(Document doc : results) {
doc.getString("EmailAddress")
}

How can I find a document in an array with MongoDB API Java?

Here's my code
ServerAddress sa = new ServerAddress("localhost", 27017);
MongoClient mongoClient = new MongoClient(sa);
MongoDatabase db = mongoClient.getDatabase("waitinglist");
MongoCollection<Document> coll = db.getCollection("users");
MongoCursor<Document> f = coll.find(eq("users.email", "marc#berger.com")).iterator();
try {
while (f.hasNext()) {
System.out.println("Mongo Cursor: " +f.next().toJson());
}
} finally {
f.close();
}
And here is how my collection looks:
{
"_id" : ObjectId("560b8b76a37991ab2d650ca9"),
"users" : [
{
"firstname" : "Marc",
"lastname" : "Berger",
"email" : "marc#berger.com",
"phone" : "12345"
},
{
"firstname" : "Arnold",
"lastname" : "Schwarzenegger",
"email" : "pumping#iron.com",
"phone" : "12345"
}]
}
I bassically want to get the document in users where the email is equal marc#berger.com, but it returns the whole document with the array as one. I think the problem is the first parameter in the eq method but I can't find a solution on google how make that statement.
You use the positional $ operator in projection in order to return only the matched element of the array. This uses the .projection() method upon .find() with the MongoDB 3.x java driver:
MongoCursor<Document> f = coll.find(eq("users.email", "marc#berger.com"))
.projection(new Document("users.$",1)).iterator();
Then all results will only return the matched array element rather than all array elements.

Complex MongoDB find queries on large documents in Java

How do I make a MongoDB query using BasicDBObjects in Java, when I wish to find all documents that contain an array of nested documents, where one of those nested documents meets all the specified criteria?
Taking the example data:
[
{
"_id":"blood_0",
"type":"O",
"list":[
{
"firstname":"John",
"lastname":"Smith",
"zipcode":"12345"
},
{
"firstname":"John",
"lastname":"Hamilton",
"zipcode":"54627"
},
{
"firstname":"Ben",
"lastname":"Brick",
"zipcode":"12345"
},
{
"firstname":"William",
"lastname":"Tell",
"zipcode":"15487"
}
]
},
{
"_id":"blood_1",
"type":"AB",
"list":[
{
"firstname":"Mary",
"lastname":"Smith",
"zipcode":"12345"
},
{
"firstname":"John",
"lastname":"Henry",
"zipcode":"54624"
},
{
"firstname":"Jacob",
"lastname":"Tell",
"zipcode":"19283"
},
{
"firstname":"William",
"lastname":"Dirk",
"zipcode":"15999"
}
]
}
]
If I only want to return the objects that contain a contact in the list that meets the criteria of firstname = William, lastname = Tell how would I go about doing that? The queries I am doing are not grouping the criteria, so I would get two results where I actually only should be getting one.
How would I do the same query but also checking for type = AB, as well as the other criteria, which would return no results?
You are looking for the $elemMatch operator. It restricts the query operators to a single element within the array of values.
In the shell your query will look like:
db.people.find( { list : { $elemMatch : { lastName:"Smith", firstName: "John" } } } )
To add the blood type:
db.people.find( {
type : "AB",
list : { $elemMatch : { lastName:"Smith", firstName: "John" } }
} )
This gets a bit verbose using the Java Driver.
DBObject elemMatch = new BasicDBObject();
elemMatch.put("lastName","Smith");
elemMatch.put("firstName","John");
DBObject query = new BasicDBObject();
query.append( "type", "AB");
query.append( "list", elemMatch);
Pass that query to one of the find() methods on the collection and you should get the documents you are looking for.
Note that the $elemMatch query operator will return the entire document, including all of the elements in the array. There is a similarly named projection operator to limit the array elements returned to only those matched.
HTH - Rob.
First things first. I really think your model is utterly wrong. Nested arrays which potentially grow indefinetly are bad for multiple reasons:
If the document exceeds it's padding when new members are written to this array, the document needs to be migrated within a data file. That is a pretty costly operation and you want to prevent it as much as you can.
BSON documents are limited to 16MB. So per blood type you could only have a limited number of people.
All queries tend to be a bit more complicated, the according code more bloated and hence slower.
So how to do it? Take these documents:
{
_id: ObjectId(),
firstName: "Mary",
lastName: "Smith",
zip: "12345",
bt: "AB"
},
{
_id: ObjectId(),
firstName: "John",
lastName: "Smith",
zip: "12345",
bt: "0"
}
With indices set like
db.people.ensureIndex({lastName:1,firstName:1})
db.people.ensureIndex({bt:1})
on the MongoDB shell, you can get what you want with
db.people.find({ lastName:"Smith", firstName: "John"})
or
db.people.find({ bt: "AB" })
This query for example translates to the following
MongoClient client = new MongoClient("localhost");
DB db = client.getDB("yourDB");
DBCollection coll = db.getCollection("yourCollection");
BasicDBOBject query = new BasicDBObject("bt","AB");
DBCursor cursor = coll.find(query);
try {
while( cursor.hasNext() ) {
System.out.println( cursor.next() );
}
} finally {
cursor.close();
}
You might find the MongoDB introduction for working with a Java driver interesting.

Updating inner doc from mongo

This is my sample doc.
{
"_id" : ObjectId("51f20148a85e39af87510305"),
"group_name" : "sai",
"privileges" : [
"Notification",
"News Letter"
],
"users" : [
{
"full_name" : "sumit",
"user_name" : "sumitdesh",
"password" : "magicmoments",
"status" : "Active"
},
{
"full_name" : "ad",
"user_name" : "asd",
"password" : "asdf",
"status" : "Active"
}
]
}
I want to replace inner doc from users array with a new doc.
This is my java code:
BasicDBObject g1=new BasicDBObject();
g1.put("full_name", "ram");
g1.put("user_name", "ram123");
g1.put("password", "pass$123");
g1.put("status", "Inactive");
BasicDBObject doc=new BasicDBObject();
doc.put("users",g1);
BasicDBObject q=new BasicDBObject("users.user_name","asd");
con.update(q,doc);
Any help is appreciated
Expected output is as follows
I want to replace inner doc with these values
{
"_id" : ObjectId("51f20148a85e39af87510305"),
"group_name" : "sai",
"privileges" : [
"Notification",
"News Letter"
],
"users" : [
{
"full_name" : "sumit",
"user_name" : "sumitdesh",
"password" : "magicmoments",
"status" : "Active"
},
{
"full_name" : "ram",
"user_name" : "ram123",
"password" : "pass$123",
"status" : "Inactive"
}
]
}
I must combine $set and $ operators, then you can update an specific item of array.
BasicDBObject g1 = new BasicDBObject();
g1.put("users.$.full_name", "ram");
g1.put("users.$.user_name", "ram123");
g1.put("users.$.password", "pass$123");
g1.put("users.$.status", "Inactive");
BasicDBObject doc = new BasicDBObject();
doc.put("$set", g1);
BasicDBObject q = new BasicDBObject("users.user_name","asd");
con.update(q,doc);
Your code will create a new document consisting only of the new user. To add a new element to an array in an existing document, use the $push operator
BasicDBObject where = new BasicDBObject("_id", new ObjectId("51f20148a85e39af87510305");
BasicDBObject doc = //... your new user object
BasicDBObject push = new BasicDBObject("$push", doc);
con.update(where, push);
To modify a field of an existing document, you can use the set-operator combined with the $-placeholder. This changes the user_name from "foo" to "bar"
BasicDBObject where = new BasicDBObject("users.user_name", "foo");
BasicDBObject value = new BasicDBObject("users.$.user_name", "bar");
BasicDBObject set = new BasicDBObject("$set", value);
con.update(where, set);
But the least headache-inducing way is to just keep the whole DBObject around when you retrieve an object from the database, mirror all modifications in the DBObject, and then call
con.save(dbObject);
An ORM wrapper library can do this for you. But while it is the easiest way, it isn't the most efficient way, because the whole document will be sent to the database. This is a problem which can be easily filed under "premature optimization" when writes are infrequent and the documents are small, but when you save often and have huge documents, it can become an issue.
This is actually fairly simple, if you follow the documentation.
The first difficulty is finding the document to update. You're looking for the user whose user_name field is 'asd', which is done, rather neatly, through the following query:
{'users.user_name': 'asd'}
The field name needs to be escaped in the mongo shell (it's a compound name) but you need not worry about that in Java.
Now that you've found your user, you need to change it. MongoDB magically stores the matched array index as $, which allows you to write the update criteria as:
{
$set: {
'users.$': {
full_name: 'ram',
user_name: 'ram123',
password: 'pass$123',
status: 'inactive'
}
}
}
You obviously know your way around the Java connector, I'll leave the transformation of my JSON object to instances of BasicDBObject to you.

How to find the smallest number in a mongo query?

I have the following objects in my mongo db:
{
"type" : "timetype"
"time" : "18"
}
{
"type" : "timetype"
"time" : "5"
}
{
"type" : "timetype"
"time" : "43"
}
{
"type" : "timetype"
"time" : "23"
}
And my java code looks like:
BasicDBObject query = new BasicDBObject();
query.put("type", "timetype");
//I don't know what to put in the (...)
DBCursor cursor = Collection.find(query).sort(...).limit(1);
I would like to find the entry with the smallest time in my mongo database that meets the query parameter but I don't know what to put in sort to make that happen.
Something along the lines of
Collection.find(query).sort(new BasicDBObject( "time" , 1 )).limit(1);
should work.

Categories

Resources