首页 > 代码库 > MongoDB for Java入门

MongoDB for Java入门

Introduction

This page is a brief overview of working with the MongoDB Java Driver.

For more information about the Java API, please refer to the online API Documentation for Java Driver.

A Quick Tour

Using the Java driver is very simple. First, be sure to include the driver jar mongo.jar in your classpath.

NOTE

The following code snippets come from the QuickTour.java example code that can be found with thedriver source.

Making a Connection

To make a connection to a MongoDB, you need to have at the minimum, the name of a database to connect to. The database doesn’t have to exist - if it doesn’t, MongoDB will create it for you.

Additionally, you can specify the server address and port when connecting. The following example shows three ways to connect to the database mydb on the local machine :

import com.mongodb.BasicDBObject;
import com.mongodb.BulkWriteOperation;
import com.mongodb.BulkWriteResult;
import com.mongodb.Cursor;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.ParallelScanOptions;

import java.util.List;
import java.util.Set;

import static java.util.concurrent.TimeUnit.SECONDS;

// To directly connect to a single MongoDB server (note that this will not auto-discover the primary even
// if it‘s a member of a replica set:
MongoClient mongoClient = new MongoClient();
// or
MongoClient mongoClient = new MongoClient( "localhost" );
// or
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// or, to connect to a replica set, with auto-discovery of the primary, supply a seed list of members
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017),
                                      new ServerAddress("localhost", 27018),
                                      new ServerAddress("localhost", 27019)));

DB db = mongoClient.getDB( "mydb" );

At this point, the db object will be a connection to a MongoDB server for the specified database. With it, you can do further operations.

NOTE

The MongoClient instance actually represents a pool of connections to the database; you will only need one instance of class MongoClient even with multiple threads. See the concurrency doc page for more information.

The MongoClient class is designed to be thread safe and shared among threads. Typically you create only 1 instance for a given database cluster and use it across your application. If for some reason you decide to create many MongoClient instances, note that:

  • all resource usage limits (max connections, etc) apply per MongoClient instance
  • to dispose of an instance, make sure you call MongoClient.close() to clean up resources

New in version 2.10.0: The MongoClient class is new in version 2.10.0. For releases prior to that, please use the Mongo class instead.

Authentication (Optional)

MongoDB can be run in a secure mode where access to databases is controlled through name and password authentication. When run in this mode, any client application must provide a name and password before doing any operations. In the Java driver, you simply do the following with a MongoClient instance:

MongoClient mongoClient = new MongoClient();
DB db = mongoClient.getDB("test");
boolean auth = db.authenticate(myUserName, myPassword);

If the name and password are valid for the database, auth will be true. Otherwise, it will be false. You should look at the MongoDB log for further information if available.

Most users run MongoDB without authentication in a trusted environment.

Getting a List Of Collections

Each database has zero or more collections. You can retrieve a list of them from the db (and print out any that are there) :

Set<String> colls = db.getCollectionNames();

for (String s : colls) {
    System.out.println(s);
}

and assuming that there are two collections, name and address, in the database, you would see

name
address

as the output.

Getting a Collection

To get a collection to use, just specify the name of the collection to the getCollection(String collectionName)method:

DBCollection coll = db.getCollection("testCollection");

Once you have this collection object, you can now do things like insert data, query for data, etc

Setting Write Concern

As of version 2.10.0, the default write concern is WriteConcern.ACKNOWLEDGED, but it can be easily changed:

mongoClient.setWriteConcern(WriteConcern.JOURNALED);

There are many options for write concern. Additionally, the default write concern can be overridden on the database, collection, and individual update operations. Please consult the API Documentation for details.

Changed in version 2.10.0: Prior to version 2.10.0, the default write concern is WriteConcern.NORMAL. Under normal circumstances, clients will typically change this to ensure they are notified of problems writing to the database.

Inserting a Document

Once you have the collection object, you can insert documents into the collection. For example, lets make a little document that in JSON would be represented as

{
   "name" : "MongoDB",
   "type" : "database",
   "count" : 1,
   "info" : {
               x : 203,
               y : 102
             }
}

Notice that the above has an “inner” document embedded within it. To do this, we can use theBasicDBObject class to create the document (including the inner document), and then just simply insert it into the collection using the insert() method.

BasicDBObject doc = new BasicDBObject("name", "MongoDB")
        .append("type", "database")
        .append("count", 1)
        .append("info", new BasicDBObject("x", 203).append("y", 102));
coll.insert(doc);

Finding the First Document in a Collection Using findOne()

To show that the document we inserted in the previous step is there, we can do a simple findOne()operation to get the first document in the collection. This method returns a single document (rather than theDBCursor that the find() operation returns), and it’s useful for things where there only is one document, or you are only interested in the first. You don’t have to deal with the cursor.

DBObject myDoc = coll.findOne();
System.out.println(myDoc);

and you should see

{ "_id" : "49902cde5162504500b45c2c" ,
  "name" : "MongoDB" ,
  "type" : "database" ,
  "count" : 1 ,
  "info" : { "x" : 203 , "y" : 102}}

NOTE

The _id element has been added automatically by MongoDB to your document. Remember, MongoDB reserves element names that start with “_”/”$” for internal use.

Adding Multiple Documents

In order to do more interesting things with queries, let’s add multiple simple documents to the collection. These documents will just be

{
   "i" : value
}

and we can do this fairly efficiently in a loop

for (int i=0; i < 100; i++) {
    coll.insert(new BasicDBObject("i", i));
}

Notice that we can insert documents of different “shapes” into the same collection. This aspect is what we mean when we say that MongoDB is “schema-free”

Counting Documents in A Collection

Now that we’ve inserted 101 documents (the 100 we did in the loop, plus the first one), we can check to see if we have them all using the getCount() method.

System.out.println(coll.getCount());

and it should print 101.

Using a Cursor to Get All the Documents

In order to get all the documents in the collection, we will use the find() method. The find() method returns a DBCursor object which allows us to iterate over the set of documents that matched our query. So to query all of the documents and print them out :

DBCursor cursor = coll.find();
try {
   while(cursor.hasNext()) {
       System.out.println(cursor.next());
   }
} finally {
   cursor.close();
}

and that should print all 101 documents in the collection.

Getting A Single Document with A Query

We can create a query to pass to the find() method to get a subset of the documents in our collection. For example, if we wanted to find the document for which the value of the “i” field is 71, we would do the following ;

BasicDBObject query = new BasicDBObject("i", 71);

cursor = coll.find(query);

try {
   while(cursor.hasNext()) {
       System.out.println(cursor.next());
   }
} finally {
   cursor.close();
}

and it should just print just one document

{ "_id" : "49903677516250c1008d624e" , "i" : 71 }

You may commonly see examples and documentation in MongoDB which use $ Operators, such as this:

db.things.find({j: {$ne: 3}, k: {$gt: 10} });

These are represented as regular String keys in the Java driver, using embedded DBObjects:

query = new BasicDBObject("j", new BasicDBObject("$ne", 3))
        .append("k", new BasicDBObject("$gt", 10));

cursor = coll.find(query);

try {
    while(cursor.hasNext()) {
        System.out.println(cursor.next());
    }
} finally {
    cursor.close();
}

Getting A Set of Documents With a Query

We can use the query to get a set of documents from our collection. For example, if we wanted to get all documents where "i" > 50, we could write:

// find all where i > 50
query = new BasicDBObject("i", new BasicDBObject("$gt", 50));

cursor = coll.find(query);
try {
    while (cursor.hasNext()) {
        System.out.println(cursor.next());
    }
} finally {
    cursor.close();
}

which should print the documents where i > 50.

We could also get a range, say 20 < i <= 30:

query = new BasicDBObject("i", new BasicDBObject("$gt", 20).append("$lte", 30));
cursor = testCollection.find(query);

try {
    while (cursor.hasNext()) {
        System.out.println(cursor.next());
    }
} finally {
    cursor.close();
}

MaxTime

MongoDB 2.6 introduced the ability to timeout individual queries:

coll.find().maxTime(1, SECONDS).count();

In the example above the maxTime is set to one second and the query will be aborted after the full second is up.

New in version 2.12.0: Added to MongoDB in 2.6

Bulk operations

Under the covers MongoDB is moving away from the combination of a write operation + get last error (GLE) and towards a write commands api. These new commands allow for the execution of bulk insert/update/remove operations. The bulk api’s are abstractions on top of this that server to make it easy to build bulk operations. There are two types of bulk operations:

  1. Ordered bulk operations.

    These operations execute all the operation in order and error out on the first write error.

  2. Unordered bulk operations.

    These operations execute all the operations in parallel and aggregates up all the errors. Unordered bulk operations do not guarantee order of execution.

Let’s look at two simple examples using ordered and unordered operations:

// 1. Ordered bulk operation
BulkWriteOperation builder = coll.initializeOrderedBulkOperation();
builder.insert(new BasicDBObject("_id", 1));
builder.insert(new BasicDBObject("_id", 2));
builder.insert(new BasicDBObject("_id", 3));

builder.find(new BasicDBObject("_id", 1)).updateOne(new BasicDBObject("$set", new BasicDBObject("x", 2)));
builder.find(new BasicDBObject("_id", 2)).removeOne();
builder.find(new BasicDBObject("_id", 3)).replaceOne(new BasicDBObject("_id", 3).append("x", 4));

BulkWriteResult result = builder.execute();

// 2. Unordered bulk operation - no guarantee of order of operation
builder = coll.initializeUnorderedBulkOperation();
builder.find(new BasicDBObject("_id", 1)).removeOne();
builder.find(new BasicDBObject("_id", 2)).removeOne();

result = builder.execute();

NOTE

For older servers than 2.6 the API will down convert the operations. To support the correct semantics for BulkWriteResult and BulkWriteException, the operations have to be done one at a time. It’s not possible to down convert 100% so there might be slight edge cases where it cannot correctly report the right numbers.

New in version 2.12.0.

parallelScan

MongoDB 2.6 added the parallelCollectionScan command that allows you to reading out an entire collection using multiple cursors.

ParallelScanOptions parallelScanOptions = ParallelScanOptions
        .builder()
        .numCursors(3)
        .batchSize(300)
        .build();

List<Cursor> cursors = coll.parallelScan(parallelScanOptions);
for (Cursor pCursor: cursors) {
    while (pCursor.hasNext()) {
        System.out.println((pCursor.next()));
    }?    }

This optimizes the IO throughput from a collection.

NOTE

ParallelScan does not work via mongos.

New in version 2.12.0: Added to MongoDB in 2.6

Quick Tour of the Administrative Functions

NOTE

The following code snippets come from the QuickTourAdmin.java example code that can be found with the driver source.

Getting A List of Databases

You can get a list of the available databases:

MongoClient mongoClient = new MongoClient();

for (String s : mongoClient.getDatabaseNames()) {
   System.out.println(s);
}

Calling mongoClient.getDB() does not create a database. Only when a database is written to will a database be created. Examples would be creating an index or collection or inserting a document.

Dropping A Database

You can drop a database by name using a MongoClient instance:

MongoClient mongoClient = new MongoClient();
mongoClient.dropDatabase("databaseToBeDropped");

Creating A Collection

There are two ways to create a collection. Inserting a document will create the collection if it doesn’t exist or calling the createCollection command.

An example of creating a capped sized to 1 megabyte:

db = mongoClient.getDB("mydb");
db.createCollection("testCollection", new BasicDBObject("capped", true)
        .append("size", 1048576));

Getting A List of Collections

You can get a list of the available collections in a database:

for (String s : db.getCollectionNames()) {
   System.out.println(s);
}

It should output

system.indexes
testCollection

NOTE

The system.indexes collection is automatically created and lists all the indexes in the database and shouldn’t be accessed directly.

Dropping A Collection

You can drop a collection by using the drop() method:

DBCollection testCollection = db.getCollection("testCollection");
testCollection.drop();
System.out.println(db.getCollectionNames());

And you should notice that testCollection has been dropped.

Getting a List of Indexes on a Collection

You can get a list of the indexes on a collection:

List<DBObject> list = coll.getIndexInfo();

for (DBObject o : list) {
   System.out.println(o.get("key"));
}

and you should see something like

{ "v" : 1 , "key" : { "_id" : 1} , "name" : "_id_" , "ns" : "mydb.testCollection"}
{ "v" : 1 , "key" : { "i" : 1} , "name" : "i_1" , "ns" : "mydb.testCollection"}
{ "v" : 1 , "key" : { "loc" : "2dsphere"} , "name" : "loc_2dsphere" , ... }
{ "v" : 1 , "key" : { "_fts" : "text" , "_ftsx" : 1} , "name" : "content_text" , ... }

Creating An Index

MongoDB supports indexes, and they are very easy to add on a collection. To create an index, you just specify the field that should be indexed, and specify if you want the index to be ascending (1) or descending (-1). The following creates an ascending index on the i field :

coll.createIndex(new BasicDBObject("i", 1));  // create index on "i", ascending

Geo indexes

MongoDB supports various geospatial indexes in this example we’ll be creating a 2dsphere index which we can query using standard GeoJson markup. To create a 2dsphere index specify the string literal “2dsphere” in the index document:

coll.createIndex(new BasicDBObject("loc", "2dsphere"));

There are various ways to query a 2dsphere index this example finds places within 500 meters of a location:

BasicDBList coordinates = new BasicDBList();
coordinates.put(0, -73.97);
coordinates.put(1, 40.77);
coll.insert(new BasicDBObject("name", "Central Park")
                .append("loc", new BasicDBObject("type", "Point").append("coordinates", coordinates))
                .append("category", "Parks"));

coordinates.put(0, -73.88);
coordinates.put(1, 40.78);
coll.insert(new BasicDBObject("name", "La Guardia Airport")
        .append("loc", new BasicDBObject("type", "Point").append("coordinates", coordinates))
        .append("category", "Airport"));


// Find whats within 500m of my location
BasicDBList myLocation = new BasicDBList();
myLocation.put(0, -73.965);
myLocation.put(1, 40.769);
myDoc = coll.findOne(
            new BasicDBObject("loc",
                new BasicDBObject("$near",
                        new BasicDBObject("$geometry",
                                new BasicDBObject("type", "Point")
                                    .append("coordinates", myLocation))
                             .append("$maxDistance",  500)
                        )
                )
            );
System.out.println(myDoc.get("name"));

It should print Central Park. See the geospatial documentation for more information.

Text indexes

MongoDB also provides text indexes to support text search of string content. Text indexes can include any field whose value is a string or an array of string elements. To create a text index specify the string literal “text” in the index document:

// create a text index on the "content" field
coll.createIndex(new BasicDBObject("content", "text"));

As of MongoDB 2.6 text indexes are now integrated into the main query language and enabled by default:

// Insert some documents
coll.insert(new BasicDBObject("_id", 0).append("content", "textual content"));
coll.insert(new BasicDBObject("_id", 1).append("content", "additional content"));
coll.insert(new BasicDBObject("_id", 2).append("content", "irrelevant content"));

// Find using the text index
BasicDBObject search = new BasicDBObject("$search", "textual content -irrelevant");
BasicDBObject textSearch = new BasicDBObject("$text", search);
int matchCount = coll.find(textSearch).count();
System.out.println("Text search matches: "+ matchCount);

// Find using the $language operator
textSearch = new BasicDBObject("$text", search.append("$language", "english"));
matchCount = coll.find(textSearch).count();
System.out.println("Text search matches (english): "+ matchCount);

// Find the highest scoring match
BasicDBObject projection = new BasicDBObject("score", new BasicDBObject("$meta", "textScore"));
myDoc = coll.findOne(textSearch, projection);
System.out.println("Highest scoring document: "+ myDoc);

and it should print:

Text search matches: 2
Text search matches (english): 2
Highest scoring document: { "_id" : 1 , "content" : "additional content" , "score" : 0.75}

For more information about text search see the text index and $text query operator documentation.