Ordenar e pegar valor de um documento em MongoDB e manipular em Java

mongodb
javafx
nosql

#1

Fala galera.
Tô criando um software de Ordens de Serviços e resolvi utilizar Java (Javafx para ser mais exato) e MongoDB pra tal fim.
Tô nos “acabamentos finais” e o que eu tô pensando é o seguinte:
Cerca de 5 a 6 pessoas irão utilizar a aplicação simultaneamente, meu pensamento inicial era de ao abrir a janela de nova OS a numeração ficar numa label lá em cima logo de cara, então pra não ocorrer de ao gerar a numeração de uma O.S.ficar igual a outra, eu pensei em criar essa numeração somente ao clicar no botão de “gerar OS”.
Pois bem, ao clicar no botão o método vai ordenar em ordem decrescente pelo campo “numeroOS”, pra a última O.S. criada aparecer em primeiro e eu pegar seu número e acrescentar +1 para esta nova.
A parte de ordenar eu sei, é só utilizar .sort() e passar o parâmetro correto pra ficar decrescente. Mas queria saber como pegar o valor de um campo específico no primeiro documento do resultado da minha pesquisa. (De preferência o código Java rsrs, pois não sei se no próprio Mongo tem como fazer isso)
Caso alguém saiba e possa me ajudar, agradeço.
Abraço jovens!


#2

Para Java + MongoDB use o findOne e pegue o campo que quiser.

DBObject dbObject = collection.findOne();
System.out.println(dbObject);

Exemplo completo:
https://www.mkyong.com/mongodb/java-mongodb-query-document/


#3

Eu recomendo fortemente que você delegue esta responsabilidade para o banco, ainda mais usando o MongoDB. Ele possui um modelo de consistência eventual então mesmo com poucas pessoas usando é relativamente fácil você ler um dados desatualizado. Você pode inserir um registro novo com o número “100” por exemplo, e algum tempinho depois outro usuário consultar o maior número em outra réplica e encontrar o número “99”.
Acho que a melhor opção é usar o $inc e criar uma função de “autoincrement” como a documentação recomenda


#4

Bacana, apesar de não ser exatamente a solução pra esse meu problema, esse artigo pode me ajudar em futuros. Valeu!
A solução que nosso amigo @davidpaniz seria o que eu preciso pra esse caso.
Abraço!


#5

Show de bola! Soluciona perfeitamente. Fiz uns testes aqui e deu certo!!
Só uma dúvida, pra essa função ser chamada no mongo a cada nova O.S. eu faço isso em Java né (utilizando mais ou menos o que o @boaglio postou ali em cima) ?
Abraço amigo, vai desculpando a ignorância, sou iniciante ainda… rs


#6

Eu nunca usei MongoDB com Java, vai depender de qual biblioteca você está usando, mas se já criou o contador e a função pra fazer o increment, tem que ver como passar a chamada da função na hora de criar o documento. Provavelmente tem algum método insert ou similar onde você passa os valores da OS pra salvar no banco. Na hora de montar e preparar o argumento para chamar este método você precisa deixar que o valor do campo numeroOS vai ser a chamada pra função no MongoDB. Dá uma procurada na documentação da biblioteca que está usando, alias, qual é a biblioteca que está usando?


#7

Nenhum, apenas Java e o Driver do Mongo pra Java.
Consegui fazer isso. Tive que fazer o seguinte, armazenei a função JS via shell no Mongo: https://docs.mongodb.com/manual/tutorial/store-javascript-function-on-server/
Depois no momento em que vou criar um ‘Document’ e ir criando os campos e seus valores, eu chamo a função, fica mais ou menos assim:

Document doc = new Document(“numeroOS”,mongo.database.runCommand(new Document("$eval", “getNextSequence(‘userid’)”)))
.append(“nomeCliente”,os.getNomeDoCliente())
.append(“emailCliente”,os.getEmail())
.append(“telefone”,os.getTelefone())

                 ............................ aqui tem mais códigos

Só tem um probleminha… quando eu salvo no mongo ele fica assim:

{
"_id": ObjectId(“5880bfdea3778c1e104eb07c”),
“numeroOS”: {
“retval”: 100005,
“ok”: 1
},
“nomeCliente”: “”,
“emailCliente”: “”,
“telefone”: “”,

}

Nesse teste passei tudo null e deixei o campo de número OS preencher só. Só que ele cria um objeto novo e passa pro campo numeroOS. Realmente iria criar um objeto pois quando executo o comando Java via método ‘runCommand’ eu tô criando um novo Documento e passando via parâmetro. Vou ter que pesquisar agora como faço pra pegar o valor que nesse caso tá em ‘retval’ e retornar só esse valor pra quando eu for criar o Documento principal da minha Ordem de Serviço. Já tenho mais ou menos em mente como vou fazer… Não sei certo, mas acho que terei que criar um método pra tratar isso, retornando o valor de um find() com os parâmetros corretos pra retornar apenas o valor de retval.
Tá mais perto do que longe! Hahaha


#8

Você tentou mudar o runCommand pra usar (new Document("$eval", "getNextSequence('userid').retval") ?
Outra coisa, me parece que o runCommand deve ser usado para executar comandos de admin. Você já deu uma olhada no doEval?


#9

O comando com o final “.retval” aqui não deu certo… o saiu do mesmo jeito e com retval null.
Dei uma pesquisada e parece que o “doEval” tá depreciado:

Eu fiz assim: juntei o new Document que executa o runCommand e já fui dando ‘append’ com os valores dos campos, ficou mais ou menos assim:

Document doc = new Document(mongo.database.runCommand(new Document("$eval",
“getNextSequence(‘userid’)”)))
.append(“nomeCliente”,os.getNomeDoCliente())
.append(“emailCliente”,os.getEmail())
.append(“telefone”,os.getTelefone())
.append(“ruaImovel”,os.getRua())

Fiz isso só pra ficar simplificar uma procura depois, já que agora o valor da O.S. está diretamente em um só documento:

  "_id": ObjectId("58879c9c5792491c0c04d325"),
  "retval": 100004,
  "ok": 1,
  "nomeCliente": "",
  "emailCliente": "",
  "telefone": "",
  "ruaImovel": "",
  "bairroImovel": "",
  "cidadeImovel": "",
  "estadoImovel": null,
  "matriculaImovel": "",
  "tipoServico": "",
  "codigoServico": "",
  "valorServico": 12,
  "valorDesloc": 2,
  "valorTotal": 14,
  "obs": "",
  "demandante": ""
}

Vou dar uma pesquisada na documentação do Mongo de como eu posso retornar o valor de um único campo de um documento. Pelo find() ou findOne() ele retorna o documento por completo, creio que possa existir uma forma de “direcionar” melhor uma query no Mongo mesmo pra sair apenas o valor do campo, no caso retornar apenas 100004 se fosse no documento acima.
Agradeço o esforço pra me ajudar, se não for pedir demais, seria de grande valia mais um help nesse caso de retornar apenas o valor, hehe.
Abraço mano!


#10

Fala cara, blz? Passando aqui pra dizer que resolvi a questão!
Vou deixar aqui a resposta pra caso alguém tenha a mesma dúvida, solucionar.
O código pode não estar 100% correto, mas tá solucionando o problema hehe. Futuramente vou estudar pra melhorar o código.

FindIterable myDoc = conn.collection.find(eq("_id",“userid”));
ArrayList docs = new ArrayList();

    myDoc.into(docs);
    
    
    docs.stream().forEach((doc) -> {            
        System.out.println(doc.get("seq"));
    });

O resultado sai assim:

…informações de conexão com mongo…
100004.0
CONSTRUÍDO COM SUCESSO (tempo total: 3 segundos)

No meu banco existe um documento pra ‘‘gerenciar’’ o número da O.S. uso uma função armazenada no próprio Mongo e incremento nesse campo “seq” e depois seto na O.S., logo a última O.S. ta com o numero atual do campo seq do documento userid. Pra melhor entendimento segue abaixo um find() do meu banco:

{
"_id": “userid”,
“seq”: 100004
}

…outros documentos…

{
"_id": ObjectId(“58879c9c5792491c0c04d325”),
“retval”: 100004,
“ok”: 1,
“nomeCliente”: “”,
“emailCliente”: “”,
“telefone”: “”,
“ruaImovel”: “”,
“bairroImovel”: “”,
“cidadeImovel”: “”,
“estadoImovel”: null,
“matriculaImovel”: “”,
“tipoServico”: “”,
“codigoServico”: “”,
“valorServico”: 12,
“valorDesloc”: 2,
“valorTotal”: 14,
“obs”: “”,
“demandante”: “”
}

Bom, foi assim que consegui pegar o campo de um documento em Mongo via Java.
Nesse exmpelo específico, tô pegando o valor da última O.S. criada, pra alertar na tela do usuário assim que ele criar.