Search code examples
mongodbmongo-java

Mongodb - append on duplicate record


I'm trying to accomplish this task in Java using mongodb. Let's say I have a list of employees (firstname, lastname, phone-number). Now, some employees can have more than one phone number.

Let's say I have a list of employees (I'm parsing an xml document):

<contact><firstname>John</firstname><lastname>Smith</lastname><phonenum>555 123 23 23</phonenum></contact>
<contact><firstname>Jane</firstname><lastname>Doe</lastname><phonenum>555 123 44 44</phonenum></contact>
<contact><firstname>John</firstname><lastname>Smith</lastname><phonenum>555 666 66 66 23</phonenum></contact>

The resulting insertions in mongodb should look like this:

{ "_id" : ObjectId("5297a3d84a9cb457a3f33b23"), "name" : "John", "lastName" : "Smith", "phone" : [  "555 123 23 23",  "555 666 66 66 23" ] }
{ "_id" : ObjectId("5297a3d84a9cb457a3f33b24"), "name" : "Jane", "lastName" : "Doe", "phone" : [  "555 123 44 44" ] }

What I've tried is first start by parsing the document and inserting the firstname and lastname. Then, querying for the firstname and lastname, if it exists, updating the record by using $push to append the phone number:

File fXmlFile = new File("contacts.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
Document doc;

try {

MongoClient mongo = new MongoClient("localhost", 27017);
DB db = mongo.getDB("testdb");
dBuilder = dbFactory.newDocumentBuilder();
DBCollection table = db.getCollection("employees");

doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("contact");

for (int temp = 0; temp < nList.getLength(); temp++) {

  Node nNode = nList.item(temp);
  BasicDBObject document = new BasicDBObject();

  if (nNode.getNodeType() == Node.ELEMENT_NODE) {

    Element eElement = (Element) nNode;

    String firstName = eElement.getElementsByTagName("name").item(0).getTextContent();
    String lastName =eElement.getElementsByTagName("lastName").item(0).getTextContent();

    document.put("name", firstName);
    document.put("lastName", lastName);
    table.insert(document);

    String phoneNumber = eElement.getElementsByTagName("phone").item(0).getTextContent();
    BasicDBObject query = new BasicDBObject();
    query.put("name", firstName);
    query.put("lastName", lastName);

    BasicDBObject push = new BasicDBObject();
    push.put("$push", new BasicDBObject("phone",phoneNumber));
    table.update(query, push);
}

}

But I'm getting the following result:

{ "_id" : ObjectId("5297a5004a9ca519fad4e94d"), "lastName" : "Smith", "name" : "John", "phone" : [  "555 123 23 23"
,  "555 666 66 66 23" ] }
{ "_id" : ObjectId("5297a5004a9ca519fad4e94e"), "lastName" : "Doe", "name" : "Jane", "phone" : [  "555 123 44 44" ]
 }
{ "_id" : ObjectId("5297a5004a9ca519fad4e94f"), "name" : "John", "lastName" : "Smith" }

So basically, there is one John Smith record with no phone number that gets added, why is that? Also why are my first two records displayed lastname first?

I'm fairly new with mongodb so this is very sloppy and quick code just to see how I can accomplish this task.

I would gladly appreciate any help.

Thanks.


Solution

  • Mongodb has the concept of upsert (insert if not exists or update if does exist).

    Try using : update(DBObject q,DBObject o, boolean upsert, boolean multi) with the upsert flag set to true.

    Something like this:

    collection.update(new BasicDBObject("name", "John").append("lastName", "Smith"), new BasicDBObject("$push", new BasicDBObject("phone", "new number")), true, false)