why does this update fail?

73 views
Skip to first unread message

lawrenc...@gmail.com

unread,
Dec 30, 2013, 2:01:11 AM12/30/13
to clojure...@googlegroups.com
I was assuming this line would work:

        (mc/update "tma" { :_id  (ObjectId. (:_id item)) } item)))))

When I use pprint on "item", I can see that :_id is a string: 

{:submit "Submit",
 :scheduled-for-deletion "false",
 "created-at[month]" "10",
 :in-response-to-item-name "wpquestions-discourse-10",
 :previous-item-name "",
 "created-at[day]" "31",
 "updated-at[m]" "30",
 :this-user-is-disabled "false",
 "updated-at[year]" "",
 "updated-at[h]" "5",
 :item-type "discourses",
 :admin-note "",
 "created-at[ampm]" "pm",
 :private "false",
 :user-item-name "wpquestions-sf_guard_user-2",
 "created-at[m]" "30",
 "updated-at[month]" "10",
 :_id "52a50ce3e4b04252e29e7cc1",
 "updated-at[day]" "31",
 "created-at[h]" "5",
 :item-name "wpquestions-discourse-11",
 :community-item-name "wpquestions",
 :machine-cookie-item-name "",
 "created-at[year]" "",
 :description "WE LOVE YOUR IDEA",
 "updated-at[ampm]" "pm"}

This function was working a month ago, but I've made some change that apparently broke it. I can not figure out what change has broken it: 


(defn persist-this-item [item]
  {:pre [
         (map? item)
         (= (type (:item-name item)) java.lang.String)
         (= (type (:item-type item)) java.lang.String)
         (if (:created-at item)
           (= (type (:created-at item)) org.joda.time.DateTime)
           true)
         ]}
  (println "This was given to monger/persist-this-item:")
   (pp/pprint item)
  (let [item (if (nil? (:created-at item))
               (assoc item :created-at (dates/current-time-as-datetime))
               item)
        item (assoc item :updated-at (dates/current-time-as-datetime))]
    (if (nil? (:_id item))
      (do
        (println " in monger/persist-this-item, we will now do an insert: ")
        (mc/insert "tma" (assoc item :_id (ObjectId.))))
      (do
        (println " in monger/persist-this-item, we will now do an update: ")
        (mc/update "tma" { :_id  (ObjectId. (:_id item)) } item)))))



Any thoughts about why the update fails? 

I also tried using the string value of :_id but that doesn't work either. 

lawrenc...@gmail.com

unread,
Dec 30, 2013, 3:02:22 AM12/30/13
to clojure...@googlegroups.com

Some of the keys were strings, so I stripped them all out. I now have a map that only has keywords for keys:

{:submit "Submit",
 :scheduled-for-deletion "false",
 :in-response-to-item-name "wpquestions-discourse-10",
 :previous-item-name "",
 :this-user-is-disabled "false",
 :item-type "discourses",
 :admin-note "",
 :private "false",
 :user-item-name "wpquestions-sf_guard_user-2",
 :_id "52a50ce3e4b04252e29e7cc1",
 :item-name "wpquestions-discourse-11",
 :community-item-name "wpquestions",
 :machine-cookie-item-name "",
 :description "wewewe"}

I thought that might simplify things. But I still get nothing. 

I have this:

      (do
        (println " in monger/persist-this-item, we will now do an update: ")
        (pp/pprint  (mc/update "tma" { :_id  (ObjectId. (:_id item)) } item))))))

Nothing prints out for the line with the pprint. 

lawrenc...@gmail.com

unread,
Dec 30, 2013, 10:56:55 AM12/30/13
to clojure...@googlegroups.com

How do I get an error message? The silence is difficult to work with. 

lawrenc...@gmail.com

unread,
Dec 31, 2013, 4:21:15 PM12/31/13
to clojure...@googlegroups.com

So, at the REPL, I switch to the namespace where I keep most of my monger queries: 

admin-dates> (in-ns 'admin.monger)
#<Namespace admin.monger>

and I make sure that "persist-this-item" is public:

admin.monger> (ns-publics 'admin.monger){paginate-results #'admin.monger/paginate-results, get-children-items #'admin.monger/get-children-items, get-parent-items #'admin.monger/get-parent-items, persist-this-item #'admin.monger/persist-this-item, establish-database-connection #'admin.monger/establish-database-connection, set-database-to-use #'admin.monger/set-database-to-use, get-distinct #'admin.monger/get-distinct, find-these-items #'admin.monger/find-these-items, remove-this-item #'admin.monger/remove-this-item, connect-to-server #'admin.monger/connect-to-server, get-count #'admin.monger/get-count}

and I call it: 
admin.monger> (admin.monger/persist-this-item {  :item-name "lawrence-testing" :item-type "whatever"       })

and get: 

NoClassDefFoundError admin/monger$persist_this_item$fn__1624  admin.monger/persist-this-item (monger.clj:39)

also: 

(persist-this-item {  :item-name "lawrence-testing" :item-type "whatever"       })
NoClassDefFoundError admin/monger$persist_this_item$fn__1624  admin.monger/persist-this-item (monger.clj:39)

Does the fn__1624 refer to an anonymous function? I am not sure what is causing that here: 

(defn persist-this-item [item]
  ;; 2013-12-09 - this is called from secretary, which gets items from other parts of
  ;; the system, and loops over them and uses monger to save to the database.
  {:pre [
         (map? item)
         (= (type (:item-name item)) java.lang.String)
         (= (type (:item-type item)) java.lang.String)
         (if (:created-at item)
           (= (type (:created-at item)) org.joda.time.DateTime)
           true)
         ]}
  (println "This was given to monger/persist-this-item:")
   (pp/pprint item)
  (let [item (if (nil? (:created-at item))
               (assoc item :created-at (dates/current-time-as-datetime))
               item)
        item (assoc item :updated-at (dates/current-time-as-datetime))]
    (if (nil? (:_id item))
      (do
        (println " in monger/persist-this-item, we will now do an insert: ")
        (pp/pprint (mc/insert "tma" (assoc item :_id (ObjectId.)))))

lawrenc...@gmail.com

unread,
Dec 31, 2013, 4:30:06 PM12/31/13
to clojure...@googlegroups.com
I finally managed to get an error: 

WriteConcernException { "serverUsed" : "/127.0.0.1:27017" , "err" : "cannot change _id of a document old

Why does monger/mongodb think that I want to change the OID? I'm using the the existing OID, but it comes from the HTML form as a string and I need to cast it back to ObjectId. The Monger documentation says I should use the string representation as an argument to the ObjectId constructor. 


(persist-this-item {  :item-name "lawrence-testing" :item-type "whatever"   :_id "52a50ce3e4b04252e29e7cc1"    })
 in monger/persist-this-item, we will now do an update: 
WriteConcernException { "serverUsed" : "/127.0.0.1:27017" , "err" : "cannot change _id of a document old:{ _id: ObjectId('52a50ce3e4b04252e29e7cc1'), answer-id: 0, community: \"wpquestions\", community-item-name: \"wpquestions\", created-at: new Date(1288546314000), description: \"enodekciw, this sounds like a good idea. I'd like to hear what others on the site have to say about this? What do you all think?\", discourse-id: 10, id: 11, in-response-to-item-name: \"wpquestions-discourse-10\", item-name: \"wpquestions-discourse-11\", item-type: \"discourses\", question-id: 0, recommendation-id: 0, status: \"\", subject: \"\", updated-at: new Date(1288546314000), user-id: 2, user-item-name: \"wpquestions-sf_guard_user-2\" } new:{ _id: \"52a50ce3e4b04252e29e7cc1\", updated-at: new Date(1388525111124), created-at: new Date(1388525111124), item-type: \"whatever\", item-name: \"lawrence-testing\" }" , "code" : 13596 , "n" : 0 , "connectionId" : 753 , "ok" : 1.0}  com.mongodb.CommandResult.getException (CommandResult.java:77)


If I look here:


To convert a string in the object id form (for example, coming from a Web form) to an ObjectId, instantiate ObjectId with an argument:

(ns my.service.server
  (:import org.bson.types.ObjectId))

;; MongoDB: convert a string to an ObjectId:
(ObjectId. "4fea999c0364d8e880c05157") ;; => #<ObjectId 4fea999c0364d8e880c05157>

Document ids in MongoDB do not have to be of the object id type, they also can be strings, integers and any value you can store that MongoDB knows how to compare order (sort). However, using ObjectIds is usually a good idea.

lawrenc...@gmail.com

unread,
Dec 31, 2013, 4:33:53 PM12/31/13
to clojure...@googlegroups.com
If I give up on ObjectId and do this instead:

  (mc/update "tma" { :_id   (:_id item) } item)))

then I do not get an exception: 

(persist-this-item {  :item-name "lawrence-testing" :item-type "whatever"   :_id "52a50ce3e4b04252e29e7cc1"    })
 in monger/persist-this-item, we will now do an update: 
#<WriteResult { "serverUsed" : "/127.0.0.1:27017" , "updatedExisting" : false , "n" : 0 , "connectionId" : 754 , "err" :  null  , "ok" : 1.0}>

but the document does not change in MongoDb, so the update failed. 

lawrenc...@gmail.com

unread,
Dec 31, 2013, 4:44:34 PM12/31/13
to clojure...@googlegroups.com

Off-topic: some links are broken in the documentation.

Here is the article about doing inserts in monger:


At the bottom is the "What To Read Next" the "Updating document" takes me to a 404 error here: 


The real article is here:

lawrenc...@gmail.com

unread,
Dec 31, 2013, 4:51:39 PM12/31/13
to clojure...@googlegroups.com
I changed the line of code to this:

 (mc/update-by-id "scores" (ObjectId. (:_id item)) {:score 1088})

and then run this again from the REPL:

(persist-this-item {  :item-name "lawrence-testing" :item-type "whatever"   :_id "52a50ce3e4b04252e29e7cc1"    })

and get:

#<WriteResult { "serverUsed" : "/127.0.0.1:27017" , "updatedExisting" : false , "n" : 0 , "connectionId" : 755 , "err" :  null  , "ok" : 1.0}>

but in the MongoDb database the document with this id has not changed:

> db.tma.find({ "item-name" : "wpquestions-discourse-11" }).pretty();
{
"_id" : ObjectId("52a50ce3e4b04252e29e7cc1"),
"answer-id" : 0,
"community" : "wpquestions",
"community-item-name" : "wpquestions",
"created-at" : ISODate("2010-10-31T17:31:54Z"),
"description" : "enodekciw, this sounds like a good idea. I'd like to hear what others on the site have to say about this? What do you all think?",
"discourse-id" : 10,
"id" : 11,
"in-response-to-item-name" : "wpquestions-discourse-10",
"item-name" : "wpquestions-discourse-11",
"item-type" : "discourses",
"question-id" : 0,
"recommendation-id" : 0,
"status" : "",
"subject" : "",
"updated-at" : ISODate("2010-10-31T17:31:54Z"),
"user-id" : 2,
"user-item-name" : "wpquestions-sf_guard_user-2"
}



Selecting data from the database works fine, but updates and inserts do not work. Any ideas? 

lawrenc...@gmail.com

unread,
Dec 31, 2013, 8:44:07 PM12/31/13
to clojure...@googlegroups.com

I should add, this was all on a localhost mongodb where no user had yet been set, and no credentials existed, so there was no need to do authentication.

lawrenc...@gmail.com

unread,
Dec 31, 2013, 8:54:59 PM12/31/13
to clojure...@googlegroups.com
Ah, I am stupid. I looked at this line dozens of times and thought "I am correctly casting :_id back to an object":

               (mc/update "tma" { :_id  (ObjectId. (:_id item)) } item)))

but of course I wasn't. The :_id inside of the "item" was still a string. I got the code working with this:

               (mc/update "tma" { :_id  (ObjectId. (:_id item)) } (assoc item :_id (ObjectId. (:_id item))))))
Reply all
Reply to author
Forward
0 new messages