-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from dizzzz/update
Update
- Loading branch information
Showing
5 changed files
with
291 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
java/src/org/exist/mongodb/xquery/mongodb/collection/Update.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/* | ||
* eXist Open Source Native XML Database | ||
* Copyright (C) 2014 The eXist Project | ||
* http://exist-db.org | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public License | ||
* as published by the Free Software Foundation; either version 2 | ||
* of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with this library; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
package org.exist.mongodb.xquery.mongodb.collection; | ||
|
||
import com.mongodb.BasicDBObject; | ||
import com.mongodb.DB; | ||
import com.mongodb.DBCollection; | ||
import com.mongodb.MongoClient; | ||
import com.mongodb.MongoCommandException; | ||
import com.mongodb.MongoException; | ||
import com.mongodb.WriteResult; | ||
import com.mongodb.util.JSON; | ||
import com.mongodb.util.JSONParseException; | ||
import org.exist.dom.QName; | ||
import static org.exist.mongodb.shared.FunctionDefinitions.PARAMETER_COLLECTION; | ||
import static org.exist.mongodb.shared.FunctionDefinitions.PARAMETER_DATABASE; | ||
import static org.exist.mongodb.shared.FunctionDefinitions.PARAMETER_MONGODB_CLIENT; | ||
import org.exist.mongodb.shared.MongodbClientStore; | ||
import org.exist.mongodb.xquery.MongodbModule; | ||
import org.exist.xquery.BasicFunction; | ||
import org.exist.xquery.Cardinality; | ||
import org.exist.xquery.FunctionSignature; | ||
import org.exist.xquery.XPathException; | ||
import org.exist.xquery.XQueryContext; | ||
import org.exist.xquery.value.FunctionParameterSequenceType; | ||
import org.exist.xquery.value.FunctionReturnSequenceType; | ||
import org.exist.xquery.value.Sequence; | ||
import org.exist.xquery.value.SequenceType; | ||
import org.exist.xquery.value.StringValue; | ||
import org.exist.xquery.value.Type; | ||
|
||
/** | ||
* Functions to save a document in mongodb | ||
* | ||
* @author Dannes Wessels | ||
*/ | ||
public class Update extends BasicFunction { | ||
|
||
private static final String UPDATE = "update"; | ||
|
||
public static final String PARAM_CRITERIA = "criteria"; | ||
public static final String DESCR_CRITERIA = "The selection criteria for the update"; | ||
|
||
public static final FunctionParameterSequenceType PARAMETER_CRITERIA | ||
= new FunctionParameterSequenceType(PARAM_CRITERIA, Type.STRING, Cardinality.ONE, DESCR_CRITERIA); | ||
|
||
public static final String PARAM_MODIFICATION = "modification"; | ||
public static final String DESCR_MODIFICATION = "The modifications to apply"; | ||
|
||
public static final FunctionParameterSequenceType PARAMETER_MODIFICATION | ||
= new FunctionParameterSequenceType(PARAM_MODIFICATION, Type.STRING, Cardinality.ONE, DESCR_MODIFICATION); | ||
|
||
public static final String PARAM_UPSERT = "upsert"; | ||
public static final String DESCR_UPSERT = "When true, inserts a document if no document matches the update query criteria"; | ||
|
||
public static final FunctionParameterSequenceType PARAMETER_UPSERT | ||
= new FunctionParameterSequenceType(PARAM_UPSERT, Type.BOOLEAN, Cardinality.ONE, DESCR_UPSERT); | ||
|
||
public static final String PARAM_MULTI = "multi"; | ||
public static final String DESCR_MULTI = "When true, updates all documents in the collection that match the update query criteria, otherwise only updates one"; | ||
|
||
public static final FunctionParameterSequenceType PARAMETER_MULTI | ||
= new FunctionParameterSequenceType(PARAM_MULTI, Type.BOOLEAN, Cardinality.ONE, DESCR_MULTI); | ||
|
||
|
||
public final static FunctionSignature signatures[] = { | ||
new FunctionSignature( | ||
new QName(UPDATE, MongodbModule.NAMESPACE_URI, MongodbModule.PREFIX), "Modify an existing document or documents in collection. By default the method updates a single document.", | ||
new SequenceType[]{ | ||
PARAMETER_MONGODB_CLIENT, PARAMETER_DATABASE, PARAMETER_COLLECTION, PARAMETER_CRITERIA, PARAMETER_MODIFICATION}, | ||
new FunctionReturnSequenceType(Type.STRING, Cardinality.ONE, "The write result, JSON formatted") | ||
), | ||
|
||
new FunctionSignature( | ||
new QName(UPDATE, MongodbModule.NAMESPACE_URI, MongodbModule.PREFIX), "Modify an existing document or documents in collection.", | ||
new SequenceType[]{ | ||
PARAMETER_MONGODB_CLIENT, PARAMETER_DATABASE, PARAMETER_COLLECTION, PARAMETER_CRITERIA, PARAMETER_MODIFICATION, PARAMETER_UPSERT, PARAMETER_MULTI}, | ||
new FunctionReturnSequenceType(Type.STRING, Cardinality.ONE, "The write result, JSON formatted") | ||
), | ||
|
||
}; | ||
|
||
public Update(XQueryContext context, FunctionSignature signature) { | ||
super(context, signature); | ||
} | ||
|
||
@Override | ||
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { | ||
|
||
try { | ||
String mongodbClientId = args[0].itemAt(0).getStringValue(); | ||
String dbname = args[1].itemAt(0).getStringValue(); | ||
String collection = args[2].itemAt(0).getStringValue(); | ||
|
||
// Check id | ||
MongodbClientStore.getInstance().validate(mongodbClientId); | ||
|
||
// Get Mongodb client | ||
MongoClient client = MongodbClientStore.getInstance().get(mongodbClientId); | ||
|
||
// Get database | ||
DB db = client.getDB(dbname); | ||
DBCollection dbcol = db.getCollection(collection); | ||
|
||
// Get data | ||
BasicDBObject criterium = (BasicDBObject) JSON.parse(args[3].itemAt(0).getStringValue()); | ||
BasicDBObject modification = (BasicDBObject) JSON.parse(args[4].itemAt(0).getStringValue()); | ||
|
||
Boolean upsert = (args.length >= 6) | ||
? args[5].itemAt(0).toJavaObject(Boolean.class) | ||
: null; | ||
|
||
Boolean multi = (args.length >= 7) | ||
? args[6].itemAt(0).toJavaObject(Boolean.class) | ||
: null; | ||
|
||
// Execute update | ||
WriteResult update = (upsert == null) | ||
? dbcol.update(criterium, modification) | ||
: dbcol.update(criterium, modification, upsert, multi); | ||
|
||
return new StringValue(update.toString()); | ||
|
||
} catch (MongoCommandException ex){ | ||
// TODO return as value? | ||
LOG.error(ex.getMessage(), ex); | ||
throw new XPathException(this, MongodbModule.MONG0005, ex.getMessage()); | ||
|
||
} catch (JSONParseException ex) { | ||
String msg = "Invalid JSON data: " + ex.getMessage(); | ||
LOG.error(msg); | ||
throw new XPathException(this, MongodbModule.MONG0004, msg); | ||
|
||
} catch (XPathException ex) { | ||
LOG.error(ex.getMessage(), ex); | ||
throw new XPathException(this, ex.getMessage(), ex); | ||
|
||
} catch (MongoException ex) { | ||
LOG.error(ex.getMessage(), ex); | ||
throw new XPathException(this, MongodbModule.MONG0002, ex.getMessage()); | ||
|
||
} catch (Throwable t) { | ||
LOG.error(t.getMessage(), t); | ||
throw new XPathException(this, MongodbModule.MONG0003, t.getMessage()); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
xquery version "3.0"; | ||
|
||
module namespace mongoMain="http://exist-db.org/mongodb/test/update"; | ||
|
||
import module namespace xqjson = "http://xqilla.sourceforge.net/lib/xqjson"; | ||
|
||
import module namespace test="http://exist-db.org/xquery/xqsuite" | ||
at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; | ||
|
||
import module namespace mongodb = "http://exist-db.org/xquery/mongodb" | ||
at "java:org.exist.mongodb.xquery.MongodbModule"; | ||
|
||
import module namespace support = "http://exist-db.org/ext/mongodb/test/support" | ||
at "./support.xqm"; | ||
|
||
|
||
(: Connect to mongodb, store token :) | ||
declare %test:setUp function mongoMain:setup() | ||
{ | ||
support:setup() | ||
}; | ||
|
||
(: Disconnect from mongodb, cleanup token :) | ||
declare %test:tearDown function mongoMain:cleanup() | ||
{ | ||
support:cleanup() | ||
}; | ||
|
||
(: | ||
: Actual tests below this line | ||
:) | ||
|
||
(: collection#update() add contents :) | ||
declare | ||
%test:assertEquals(1,1) | ||
function mongoMain:update_overwrite() { | ||
let $mongodbClientId := support:getToken() | ||
let $insert := mongodb:insert($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 1 , y : 2 , z : 3 }") | ||
|
||
let $update := mongodb:update($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 1 }", "{'$set' : { q : 4 }}") | ||
|
||
return | ||
( | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ x : 1 }"), | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ q : 4 }") | ||
) | ||
}; | ||
|
||
|
||
(: collection#update() noupsert contents :) | ||
declare | ||
%test:assertEquals(0) | ||
function mongoMain:update_noupsert() { | ||
let $mongodbClientId := support:getToken() | ||
|
||
let $update := mongodb:update($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 2 }", "{ qa : 4 }", false(), false()) | ||
|
||
return | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ qa : 4 }") | ||
}; | ||
|
||
(: collection#update() upsert contents :) | ||
declare | ||
%test:assertEquals(1) | ||
function mongoMain:update_upsert() { | ||
let $mongodbClientId := support:getToken() | ||
|
||
let $update := mongodb:update($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 3 }", "{ qb : 4 }", true(), false()) | ||
|
||
return | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ qb : 4 }") | ||
}; | ||
|
||
|
||
(: collection#update() multi, 2 documents :) | ||
declare | ||
%test:assertEquals(2,2) | ||
function mongoMain:update_multi() { | ||
let $mongodbClientId := support:getToken() | ||
let $insert1 := mongodb:insert($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 10 , y : 1 , z : 3 }") | ||
let $insert2 := mongodb:insert($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 10 , y : 2 , z : 3 }") | ||
|
||
let $update := mongodb:update($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 10 }", "{'$set' : { qc : 4 }}", false(), true()) | ||
|
||
return | ||
( | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ x : 10 }"), | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ qc : 4 }") | ||
) | ||
}; | ||
|
||
(: collection#update() nomulti, 2 documents :) | ||
declare | ||
%test:assertEquals(2,1) | ||
function mongoMain:update_nomulti() { | ||
let $mongodbClientId := support:getToken() | ||
let $insert1 := mongodb:insert($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 20 , y : 1 , z : 3 }") | ||
let $insert2 := mongodb:insert($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 20 , y : 2 , z : 3 }") | ||
|
||
let $update := mongodb:update($mongodbClientId, $support:database, $support:mongoCollection, | ||
"{ x : 20 }", "{'$set' : { qd : 4 }}", false(), false()) | ||
|
||
return | ||
( | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ x : 20 }"), | ||
mongodb:count($mongodbClientId, $support:database, $support:mongoCollection, "{ qd : 4 }") | ||
) | ||
}; | ||
|
||
|