From system.profile collection I have documents like this:
{
"op" : "command",
"ns" : "..",
"command" : {
"count" : "..",
"query" : {
"$and" : [
...
]
}
},
"responseLength" : 48,
"millis" : 18,
}
Some queries don't have the command field instead they have 'query' field. I want to check if 'command' field exist. If it does then append that to my Stringbuilder object, if not append 'query'.
UPDATE:
I have tried to use Projection as suggested by Davide by but still I am not finding a way to checking if query exist, if it does then append that.
DBCollection collection = mongoTemplate.getCollection("system.profile");
DBObject query = new BasicDBObject("command", new BasicDBObject("$exists",true));
BasicDBObject fields = new BasicDBObject("command",1).append("millis", 1).append("ts", 1);
DBCursor cursor = collection.find(query, fields);
while(cursor.hasNext()) {
sb.append(cursor.next());
sb.append(System.getProperty("line.separator"));
}
return sb;
}
You need to use the following method:
public DBCursor find(DBObject query, DBObject projection);
From java doc:
projection - specifies which fields MongoDB will return from the documents in the result set.
Related
Following is the structure of my MongoDB document userActivity.
{
"_id" : ObjectId("5e49569f93e956eeb28eb8a6"),
"userId" : "123",
"likes" : {
"videos" : [
{
"_id" : "abc",
"title" : "This video is part of test setup",
}
]
}
}
I am using Spring Data MongoOperations to manipulate MongoDB collections. And below is the code to remove a video from videos array in likes sub-document. I have tried to first filter the document as per the user's userId. And then apply filter to update function as per videoId.
public UpdateResult removeVideoLike(String videoId, String userId) {
Query queryUser = Query.query( Criteria.where("userId").is(userId) );
Query queryVideo = Query.query( Criteria.where("id").is(videoId) );
Update update = new Update().pull("likes.videos", queryVideo );
return mongoOperations.updateFirst( queryUser , update, UserActivity.class );
}
This runs without errors but the entry is not removed. The UpdateResult has following values
matchedCount = 1
modifiedCount = 0
upsertedId = null
I am confused if it is able to match the entry in the array, why it is not removing it? What I am missing?
Suppose we have the following documents in a MongoDB collection:
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":"circle",
"color":"green"
}
]
}
And the MongoDB query is
db.test.find({"shapes.color": "red"}, {_id: 0, 'shapes.$': 1});
Can someone tell me how to write it in Java?
I am using:
List<BasicDBObject> obj = new ArrayList<>();
obj1.add(new BasicDBObject("shapes.color", "red"));
List<BasicDBObject> obj1 = new ArrayList<>();
obj2.add(new BasicDBObject("shapes.$", "1"));
BasicDBObject parameters1 = new BasicDBObject();
parameters1.put("$and", obj1);
DBCursor cursor = table.find(parameters1,obj2).limit(500);
and I am not getting anything.
The syntax of the Mongo Shell find function is:
db.collection.find(query, projection)
query document Optional. Specifies selection filter using query operators. To return all documents in a collection, omit this parameter or pass an empty document ({}).
projection document Optional. Specifies the fields to return in the documents that match the query filter.
When translating this for execution by the Mongo Java driver you need to construct separate BasicDBObject instances for;
the query
the projection
Here's an example:
MongoCollection<Document> table = ...;
// {"shapes.color": "red"}
BasicDBObject query = new BasicDBObject("shapes.color", "red");
// {_id: 0, 'shapes.$': 1}
BasicDBObject projection = new BasicDBObject("shapes.$", "1").append("_id", 0);
FindIterable<Document> documents = table
// assign the query
.find(query)
// assign the projection
.projection(projection);
System.out.println(documents.first().toJson());
Given the sample documents included in your question the above code will print out:
{
"shapes": [
{
"shape": "circle",
"color": "red"
}
]
}
This is identical to the output from db.test.find({"shapes.color": "red"}, {_id: 0, 'shapes.$': 1});.
I am using Java driver for mongo-db and trying to add multiple query criteria using BasicDBObjectBuilder. I have a text field where an XML is stored as String so we are using regex to form the query.
Below is my query and the output I am getting:
regexQuery.put("REQUEST_XML",BasicDBObjectBuilder
.start("$regex", ".*Main>[\r\n]<.?.?.?.?action>"+MainValue+".*")
.add("$regex", ".*Details>[\r\n]<.?.?.?.?action>" + DetailValue+ ".*").get());
regexQuery.put("NAME", "Video");
What I am getting as query is :
{ "REQUEST_XML" : { "$regex" : ".*Details>[\r\n]<.?.?.?.?action>Change.*"} , "NAME" : "Video"}
The first part with .start("$regex", ".Main>[\r\n]<.?.?.?.?action>"+MainValue+".") is not getting added to query.
Can you please let me know what is the issue ?
You are overwriting the key value pair. "$regex", ".*Details>[\r\n]<.?.?.?.?action>" + DetailValue+ ".*" overwrites "$regex", ".*Main>[\r\n]<.?.?.?.?action>"+MainValue+".*".
Use $or to pass both regex expression.
Something like
BasicDBObject regexQuery = new BasicDBObject();
regexQuery.put("$or", Arrays.asList(new BasicDBObject("REQUEST_XML", new BasicDBObject("$regex", ".*Main>[\r\n]<.?.?.?.?action>"+".*")),
new BasicDBObject("REQUEST_XML", new BasicDBObject("$regex", ".*Details>[\r\n]<.?.?.?.?action>"+".*"))));
regexQuery.put("NAME", "Video");
This should output query like
{ "$or" : [{ "REQUEST_XML" : { "$regex" : ".*Main>[\r\n]<.?.?.?.?action>.*" } }, { "REQUEST_XML" : { "$regex" : ".*Details>[\r\n]<.?.?.?.?action>.*" } }], "NAME" : "Video" }
Using 3.x driver
import static com.mongodb.client.model.Filters.or;
import static com.mongodb.client.model.Filters.regex;
Bson regexQuery = or(regex("REQUEST_XML", ".*Main>[\r\n]<.?.?.?.?action>"+".*"), regex("$regex", ".*Details>[\r\n]<.?.?.?.?action>"+".*"));
I have a mongo collection with objects like these:
[
{
"_id" : "a2d",
"entityType" : "Location",
"type" : "STRING",
},
{
"_id" : "a1_order",
"entityType" : "Order",
"type" : "STRING",
}
]
Trying to append the _entityType to all document's id where it is not present at the end id the id (the first object in the above case).
Using mongo with Spring, but I'm already stuck with the first step, to get all the objects with no entityType in id.
Thinking about something like this, with regex, but I'm not sure how should it look like:
Query query = new Query();
query.addCriteria( Criteria.where( "id" ).regex( "here i need the entity type of the current document" ) );
You can build your regex by '^' ('starts with' Regex).
So you need a function who point in all documents and check this filter
List<Document> result = new ArrayList<Document>();
StringBuilder idPrefix = new StringBuilder();
idPrefix.append("^");
idPrefix.append(idCode);
idPrefix.append("_");
List<Bson> filters = new ArrayList<Bson>();
filters.add(Filters.regex("_id", keyPrefix.toString()));
for (Document d : yourCollections.find(Filters.and(filters)))
list.add(d);
You actually want a "reverse regex" here, as you need to use the data in the document in order to match on another field.
Presently you can really only do this with MongoDB using $where, which evaluates JavaScript on the server. So for spring mongo, you need the BasicQuery instead, so we can construct from BasicDBObject and Code primatives:
BasicDBObject basicDBObject = new BasicDBObject("$where",
new Code("!RegExp('_' + this.entityType + '$','i').test(this.id)"));
BasicQuery query = new BasicQuery(basicDBObject);
That will test the "id" field in the document to see if it matches the value from entityType at the "end of the string" and without considering "case". The ! is a Not condition, so the "reverse" of the logic is applied to "not match" where the field actually did end that way.
Following is my Java controller method code
public List<MyClass> getStudentList(String studentName){
studentName = ".*" + studentName + ".*";
/* BasicDBObject field = new BasicDBObject();
field.put("regNo", 1);
field.put("name", 1);
field.put("collName", 1);
field.put("deptName", 1); */
Query query = new Query(Criteria.where("name").regex(studentName, "i"));
return mongoTemplate.find(query,MyClass.class, COLLECTION_NAME);
}
My Db looks like this
"regNo" : "1234", "name" : "ABCD", "collName" : "UNIVERSITY COLLEGE", "deptName" : "B.E. Computer Science and Engineering", "result" : [ { "subjCode" : "CS2251", "grade" : "E", "result" : "PASS", "subjName" : "Design and Analysis of Algorithms" }]
I want to select only regNo, name, collName and deptName. How can I do this?
Add this statement to query:
query.fields().include("regNo").include("name").include("collName").include("deptName").exclude("_id");
APPEND
If your codes like:
public List<MyClass> getStudentList(String studentName){
studentName = ".*" + studentName + ".*";
/* BasicDBObject field = new BasicDBObject();
field.put("regNo", 1);
field.put("name", 1);
field.put("collName", 1);
field.put("deptName", 1); */
Query query = new Query(Criteria.where("name").regex(studentName, "i"));
query.fields().include("regNo").include("name").include("collName").include("deptName").exclude("_id");
return mongoTemplate.find(query,MyClass.class, COLLECTION_NAME);
}
It should be fine.
By the query string you provided as:
var q = {
Query : {
"name" : {
"$regex" : ".*valueSearched.*",
"$options" : "i"
}
},
Fields : {
"collName" : 1,
"results" : 0, // disallowed
"_id" : 0,
"de‚Äå‚ÄãptName" : 1,
"name" : 1,
"regNo" : 1
}
};
You actually perform something similar to
query.fields().include("collName").exclude("results").exclude("_id").include("de‚Äå‚ÄãptName").include("name").include("regNo");
instead.
Please check your code accordingly. Maybe you've called query.fields().exculude("results") somewhere; ELSE, it has a bug from some part. :)
The regulation for including and excluding fields are:
If you include some fields, then only return these fields and
"_id" will return implicitly;
only "_id" is allowed to exclude;
If you exclude some normal fields, other fields will returned and
can not include other fields;
See here,it is deprecated but help you to understand
public DBCursor find(DBObject query,
DBObject fields,
int numToSkip,
int batchSize,
int options)
http://api.mongodb.org/java/current/com/mongodb/DBCollection.html#find%28com.mongodb.DBObject,%20com.mongodb.DBObject,%20int,%20int%29
If you dont want any warning ,you may use DBCursor Object.
public DBCursor(DBCollection collection,
DBObject q,
DBObject k,
ReadPreference preference)
Initializes a new database cursor
Parameters:
collection - collection to use
q - query to perform
k - keys to return from the query
preference - the Read Preference for this query
I don't use java driver but it shouldn't be much difficult.
For this issue you have to use #JsonInclude(value=Include.NON_NULL) in your pojo class like this:
#JsonInclude(value=Include.NON_NULL)
String id;