2017-03-16 6 views
0

Ich möchte mongodbs oplog mit Java und wenn möglich die Feder mongodb Integration abfragen. Mein Problem ist die folgende Abfrage von Java zu erstellen:Abfrage oplog timestamp mit Frühling mongo

db['oplog.rs'].find({ "ts": { $gt: Timestamp(1489568405,34) }, $and: [ { "ns": "myns" } ] }) 

ich ein paar Dinge wie BsonTimestamp oder BSONTimestamp versucht haben, die zu falschen querys führen. Verwendung

BasicQuery({ "ts": { $gt: Timestamp(1489568405,34) }, $and: [ { "ns": "myns" } ] }) 

führen zu einem Fehler in dem JSON Parser des Java mongodb Treibers.

Irgendwelche Hinweise?

Thx Jürgen

Ein typischer Datensatz sieht wie folgt aus:

{ 
    "ts" : Timestamp(1489567144, 2), 
    "t" : NumberLong(2), 
    "h" : NumberLong(7303473893196954969), 
    "v" : NumberInt(2), 
    "op" : "i", 
    "ns" : "asda.jam", 
    "o" : { 
     "_id" : NumberInt(2), 
     "time" : ISODate("2017-03-15T08:39:00.000+0000"), 
     "roadDesc" : { 
      "roadId" : NumberInt(28102917), 
      "roadName" : "A480 W" 
     }, 
     "posUpFront" : NumberInt(1003), 
     "posDownFront" : NumberInt(1003), 
     "_class" : "de.heuboe.acaJNI.test.Jam" 
    } 
} 

Antwort

0

Sie so etwas wie unten versuchen.

Query query = Query.query(Criteria.where("ts").gt(new BSONTimestamp(1489568405, 34)).andOperator(Criteria.where("ns").is("myns"))); 
List<BasicDBObject> basicDBObjects = mongoTemplate.find(query, BasicDBObject.class, "oplog.rs"); 
+0

Thx für Ihre Antwort aber es funktioniert nicht. Der obige Code führt zu folgender Abfrage {Suche mit Abfrage: {"ts": {"$ gt": {"inc": 34, "Zeit": {"$ date": "2017-03-15T09: 00: 05.000Z "}}}," $ und ": [{" ns ":" myns "}]}} was zu einem leeren Ergebnis führt. – JayBee

+0

Ihre Begrüßung. Können Sie einen Datensatz hinzufügen, den Sie abfragen möchten? – Veeram

+0

Ich habe meiner Frage einen Datensatz zur besseren Lesbarkeit hinzugefügt. Danke für Ihre Mühe. – JayBee

2

Mongo hat eine erweiterte JSON Syntax für Konstrukte wie NumberLong, Zeitstempel- usw., die auf der Schale Mongo arbeitet. Damit es in Java-Code funktioniert, haben sie einen strikten JSON-Modus, in dem diese Operatoren mit JSON (https://docs.mongodb.com/manual/reference/mongodb-extended-json/#bson-data-types-and-associated-representations) dargestellt werden. Um dies mit Java zu tun, können Sie einen benutzerdefinierten Konverter erstellen und ihn in Ihrem MappingMongoConverter registrieren (siehe unten stehendes Snippet). Der Konverter sollte den Datentyp (z. B. BSONTimestamp) in das richtige strikte JSON-Dokumentformat übersetzen.

@WritingConverter 
public class BsonTimestampToDocumentConverter implements Converter<BSONTimestamp, Document> { 

    private static final Logger LOGGER = LoggerFactory.getLogger(BsonTimestampToDocumentConverter.class); 

    public BsonTimestampToDocumentConverter() { 
    // 
    } 

    @Override 
    public Document convert(BSONTimestamp source) { 
    LOGGER.trace(">>>> Converting BSONTimestamp to Document"); 
    Document value = new Document(); 
    value.put("t", source.getTime()); 
    value.put("i", source.getInc()); 
    return new Document("$timestamp", value); 
    } 
} 

Registrieren Sie in den MappingMongoConverter wie diese

public MappingMongoConverter syncLocalMappingMongoConverter() throws Exception { 
    MongoMappingContext mappingContext = new MongoMappingContext(); 
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(syncLocalDbFactory()); 
    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); 
    converter.setCustomConversions(customConversions()); 

    return converter; 
} 


    private CustomConversions customConversions() { 
    List<Converter<?, ?>> converterList = new ArrayList<>(); 
    converterList.add(new BsonTimestampToDocumentConverter()); 
    // add the other converters here 
    return new CustomConversions(CustomConversions.StoreConversions.NONE, converterList); 
} 

Hier ist ein Beispiel, wo ich es verwendet, um die oplog Repository abzufragen Aufzeichnungen nach einer bestimmten Zeit zurückzubringen (der Sync wurde im Repository zu unterscheiden verwendet es aus reaktiven Async-Sachen, an denen ich gearbeitet habe. Das Async-Repository sieht genauso aus, außer dass es ReactiveMongoRepository erweitern sollte. Die OplogRecord-Klasse ist eine Java-Bean, die ich so erstellt habe, dass sie der Struktur eines MongoDb-Oplog-Datensatzes entspricht.

public interface SyncOplogRepository extends MongoRepository<OplogRecord, Long> { 

    @Query(value = "{ \"op\": { $nin: ['n', 'c'] } }") List<OplogRecord> findRecordsNotEqualToNOrC(); 

    @Query(value = "{'ts' : {$gte : ?0}, \"op\": { $nin: ['n', 'c'] } }") 
    List<OplogRecord> findRecordsNotEqualToNOrCAfterTime(BSONTimestamp timestamp); 

    @Query(value = "{'ts' : {$lt : ?0}, \"op\": { $nin: ['n', 'c'] } }") 
    List<OplogRecord> findRecordsNotEqualToNOrCBeforeTime(BSONTimestamp timestamp); 

} 

OplogRecord Klasse

import com.mongodb.DBObject; 
import org.bson.BsonTimestamp; 
import org.bson.types.BSONTimestamp; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.data.annotation.Id; 
import org.springframework.data.mongodb.core.mapping.Document; 

import java.util.Map; 


@Document(collection = "oplog.rs") 
public class OplogRecord { 

    @Id 
    private Long id; 

    /** 
    * Timestamp 
    */ 
    private BsonTimestamp ts; 

    /** 
    * Unique id for this entry 
    */ 
    private Long h; 

    /** 
    * DB and collection name of change. 
    */ 
    private String ns; 

    /** 
    * The actual document that was modified/inserted/deleted 
    */ 
    private Map<String, Object> o; 

    /** 
    * The operation that was performed 
    */ 
    private String op; 

    /** 
    * ?? 
    */ 
    private Long t; 

    /** 
    * ?? 
    */ 
    private Integer v; 

    public BsonTimestamp getTs() { 
    return ts; 
    } 

    public void setTs(BsonTimestamp ts) { 
    this.ts = ts; 
    } 

    public Long getH() { 
    return h; 
    } 

    public void setH(Long h) { 
    this.h = h; 
    } 

    public String getNs() { 
    return ns; 
    } 

    public void setNs(String ns) { 
    this.ns = ns; 
    } 

    public Map<String, Object> getO() { 
    return o; 
    } 

    public void setO(Map<String, Object> o) { 
    this.o = o; 
    } 

    public String getOp() { 
    return op; 
    } 

    public void setOp(String op) { 
    this.op = op; 
    } 

    public Long getT() { 
    return t; 
    } 

    public void setT(Long t) { 
    this.t = t; 
    } 

    public Integer getV() { 
    return v; 
    } 

    public void setV(Integer v) { 
    this.v = v; 
    } 
} 

~
~

+0

Thx für diese Antwort. Ich habe versucht, einen CustomConverter zu verwenden, aber es hat nicht funktioniert. Könnten Sie mir bitte zeigen, wie Sie den OplogRecord modelliert haben? – JayBee

+0

Die OplogRecord-Klasse wurde hinzugefügt. Es ist nur ein POJO. Stellen Sie sicher, dass der verwendete MappingMongoContext tatsächlich den von Ihnen registrierten Konverter enthält. – Raghavan

+0

Immer noch kann es nicht funktionieren. Meine Abfrageergebnisse zu: – JayBee

0

Sie können mit org.bson.BsonTimestamp filtern.

BsonTimestamp lastReadTimestamp = new BsonTimestamp(1489568405, 34); 
Bson filter = new Document("$gt", lastReadTimestamp); 

Und dann können Sie entweder finden, wie diese,

oplogColl.find(new Document("ts", filter)); 

Oder Sie einen bailable Cursor erstellen und durch die Dokumente wie folgt durchlaufen,

MongoCursor oplogCursor = 
        oplogColl 
          .find(new Document("ts", filter)) 
          .cursorType(CursorType.TailableAwait) 
          .noCursorTimeout(true) 
          .batchSize(1000) 
          .iterator();