简体   繁体   中英

How to get a specific field in an object Array in MongoDB using Java?

I have a data in MongoDB collection named "userCollection" as follow:

ID: "123"
name: "Tom"
age: 19
favprogram: (This is an Array)
{
    0: (This is an Object)
    {
        name: "Program"
        genre: "Thriller"
        programID: "001"
    }
    1:
    {
        name: "Program"
        genre: "Thriller"
        programID: "002"
    }
}

Some programs have the same name but their programIDs are unique.

My code to create an object in favprogram array (it works):

DBObject userQuery = new BasicDBObject("ID", 123);
DBObject favprogram = new BasicDBObject("favprogram", new BasicDBObject("name", "Program")
                            .append("genre", "Thriller")
                            .append("programID", "001"));
userCollection.update(userQuery, new BasicDBObject("$push", favprogram));

However, the following code does not work to get the programID from the user whose ID is "123".

DBObject query = new BasicDBObject("ID", "123");
DBCursor cursor = userCollection.find(query);
String programID = (String) cursor.next().get("favprogram.programID");

My question is, I would like to search for a specific user ID (eg, "123") and get all of his programIDs. But it seems that I could never get it right (got null every time). Thanks in advance!

Firstly, you should try to structure your Json as valid Json - it helps anyone who is participating to assist you. I assume you are starting with Json similar to...

{
"_id" : ObjectId("6080b26dc05e721a15f04d37"),
"ID" : "123",
"name" : "Tom",
"age" : 19,
"favprogram" : [
    {
        "name" : "Program",
        "genre" : "Thriller",
        "programID" : "001"
    },
    {
        "name" : "Program",
        "genre" : "Thriller",
        "programID" : "002"
    }
]
}

Assuming this Json is correct, I also assume you are trying to construct the following aggregate query, but using Java...

db.userCollection.aggregate([
{ $match : {
         "ID": "123"
    }
},
{ $unwind: { 
        path: "$favprogram",
        preserveNullAndEmptyArrays: true
    }
},
{
    $project: {
        _id: 0,
        "messageid": "$favprogram.programID"
    }
}
])

There are probably many ways to do what you are asking, this is merely one approach. If you find this query structure appropriate, then this Java code will execute such an Aggregate...

package test.barry;

public class Main {
    public static void main(String[] args) {

        // CONNECTION TO THE DATABASE
        // =============================

        com.mongodb.MongoClientSettings mongoClientSettings = com.mongodb.MongoClientSettings.builder()
                .applyConnectionString(new com.mongodb.ConnectionString("mongodb://testuser:mysecret@localhost:42011,localhost:42012,localhost:42013/?replicaSet=replSet&w=majority&readConcernLevel=majority&readPreference=primary&authSource=admin&retryWrites=true&maxPoolSize=10&waitQueueTimeoutMS=1000"))
                .build();
        
        com.mongodb.client.MongoClient client = com.mongodb.client.MongoClients.create(mongoClientSettings);

        com.mongodb.client.MongoDatabase db = client.getDatabase("javatest");
        com.mongodb.client.MongoCollection<org.bson.Document> collection = db.getCollection("userCollection");


        // QUERY THE DATABASE
        // ===================
        java.util.List<org.bson.conversions.Bson> pipeline = new java.util.ArrayList<org.bson.conversions.Bson>();

        org.bson.conversions.Bson filter = com.mongodb.client.model.Filters.eq("ID", "123");
        pipeline.add(com.mongodb.client.model.Aggregates.match(filter));

        com.mongodb.client.model.UnwindOptions unwindOptions = new com.mongodb.client.model.UnwindOptions();
        unwindOptions.preserveNullAndEmptyArrays(true);
        pipeline.add(com.mongodb.client.model.Aggregates.unwind("$favprogram", unwindOptions));
        
        pipeline.add(com.mongodb.client.model.Aggregates.project(
            com.mongodb.client.model.Projections.fields(
                com.mongodb.client.model.Projections.excludeId(), 
                com.mongodb.client.model.Projections.computed("messageid", "$favprogram.programID")) 
            )
        );

        com.mongodb.client.AggregateIterable<org.bson.Document> iterable1 = collection.aggregate(pipeline);

        // AUTO-CLOSABLE TRY
        try(com.mongodb.client.MongoCursor<org.bson.Document> cursor1 = iterable1.iterator())
        {
            while (cursor1.hasNext())
            {
                org.bson.Document queriedDocument1 = cursor1.next();
                System.out.println(String.format("messageid: %s", queriedDocument1.get("messageid")));
            }
        }
    }
}

Here is a POM.XML to use with this program. This program was tested before submission...

<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test.barry</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>test</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${basedir}</outputDirectory>
                            <finalName>Test</finalName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>test.barry.Main</mainClass>
                                </transformer>
                            </transformers>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-sync</artifactId>
            <version>4.2.0</version>
        </dependency>
    </dependencies>
</project>

Good luck!

By the way, the continued use of BasicDBObject is the old way of doing this. Compare to the Bson helpers such as...

org.bson.conversions.Bson filter = com.mongodb.client.model.Filters.eq("_id", insertedDocument.get("_id"));
org.bson.conversions.Bson sort = com.mongodb.client.model.Sorts.ascending("lastName");
org.bson.conversions.Bson projection = com.mongodb.client.model.Projections.exclude("lastName");

I finally managed to get all programIDs from the user whose ID is "123".

DBObject query = new BasicDBObject("ID", "123");
DBCursor cursor = userCollection.find(query);
// e.g. {"name": "Tom", "favprogram": {favprogram0, favprogram1, ... }}
BasicDBList favProgramList = (BasicDBList) cursor.next().get("favprogram");
// declare a String array
String [] programIDArray = new String[favProgramList.size()]
// iterate through the favProgramList
for (int i = 0; i < favProgramList.size(); i++) {
    DBObject result = (DBObject) favProgramList.get(i);
    programIDArray[i] = (String) result.get("programID");
}
cursor.close();

Now all the programIDs of that user are put into programIDArray.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM