ApexCharts gradient colorstops calculations thrown off when data series contains null values and yaxis min property is modified - linear-gradients

I am using ApexCharts to generate a Line time-series that could contain null values. When no null values exist the chart is rendered correctly, however when null values are inserted in the series, the gradient colorstops are shifted, the calculation for the position on the chart is thrown off and the color change happens in the wrong part of the chart.
To illustrate the issue, I have added dotted lines as annotations to display where the line chart should transition into a different color. You can check the different renderings in the codepen links below.
Playing with the different options, I was able to determine that what is causing the miscalculation is when the yaxis min property is changed from the default. As you can see in the code below I'm modifying it to -20 (ApexCharts defaults this to the minimum value in the dataset, zero in this example).
Why is the calculation thrown off when the data set contains null values?
Is this a bug? or is there something I'm missing?
var options = {
chart: {
height: 380,
width: 1000,
type: "line",
foreColor: '#6D6D6D'
},
series: [
{
name: "Series 1",
data: [
{x: new Date('2022-07-15 1:30 AM').getTime(), y: 0},
{x: new Date('2022-07-15 2:00 AM').getTime(), y: 7.25},
{x: new Date('2022-07-15 2:30 AM').getTime(), y: 15.32},
{x: new Date('2022-07-15 3:00 AM').getTime(), y: 20.35},
{x: new Date('2022-07-15 3:30 AM').getTime(), y: 20.42},
{x: new Date('2022-07-15 4:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-15 4:30 AM').getTime(), y: 20.44},
{x: new Date('2022-07-15 5:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-15 5:30 AM').getTime(), y: 29.92},
{x: new Date('2022-07-15 6:00 AM').getTime(), y: 39.04},
{x: new Date('2022-07-15 6:30 AM').getTime(), y: 38.15},
{x: new Date('2022-07-15 7:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-15 7:30 AM').getTime(), y: 20.44},
{x: new Date('2022-07-15 8:00 AM').getTime(), y: 29.92},
{x: new Date('2022-07-15 8:30 AM').getTime(), y: 39.04},
{x: new Date('2022-07-15 9:00 AM').getTime(), y: 38.15},
{x: new Date('2022-07-15 9:30 AM').getTime(), y: 43.21},
{x: new Date('2022-07-15 10:00 AM').getTime(), y: 48.63},
{x: new Date('2022-07-15 10:30 AM').getTime(), y: 58.94},
{x: new Date('2022-07-15 11:00 AM').getTime(), y: 69.19},
{x: new Date('2022-07-15 11:30 AM').getTime(), y: 69.38},
{x: new Date('2022-07-15 12:00 PM').getTime(), y: 79.54},
{x: new Date('2022-07-15 12:30 PM').getTime(), y: 89.75},
{x: new Date('2022-07-15 1:00 PM').getTime(), y: 99.73},
{x: new Date('2022-07-15 1:30 PM').getTime(), y: 100},
{x: new Date('2022-07-15 2:00 PM').getTime(), y: 98.23},
{x: new Date('2022-07-15 2:30 PM').getTime(), y: 97.79},
{x: new Date('2022-07-15 3:00 PM').getTime(), y: 83.85},
{x: new Date('2022-07-15 3:30 PM').getTime(), y: 68.15},
{x: new Date('2022-07-15 4:00 PM').getTime(), y: 28.54},
{x: new Date('2022-07-15 4:30 PM').getTime(), y: 0},
{x: new Date('2022-07-15 5:00 PM').getTime(), y: 7.25},
{x: new Date('2022-07-15 5:30 PM').getTime(), y: 15.32},
{x: new Date('2022-07-15 6:00 PM').getTime(), y: 20.35},
{x: new Date('2022-07-15 6:30 PM').getTime(), y: 20.42},
{x: new Date('2022-07-15 7:00 PM').getTime(), y: 20.44},
{x: new Date('2022-07-15 7:30 PM').getTime(), y: 20.44},
{x: new Date('2022-07-15 8:00 PM').getTime(), y: 20.44},
{x: new Date('2022-07-15 8:30 PM').getTime(), y: 29.92},
{x: new Date('2022-07-15 9:00 PM').getTime(), y: 39.04},
{x: new Date('2022-07-15 9:30 PM').getTime(), y: 38.15},
{x: new Date('2022-07-15 10:00 PM').getTime(), y: 20.44},
{x: new Date('2022-07-15 10:30 PM').getTime(), y: 20.44},
{x: new Date('2022-07-15 11:00 PM').getTime(), y: 29.92},
{x: new Date('2022-07-15 11:30 PM').getTime(), y: 39.04},
{x: new Date('2022-07-16 12:00 AM').getTime(), y: 38.15},
{x: new Date('2022-07-16 12:30 AM').getTime(), y: 43.21},
{x: new Date('2022-07-16 1:00 AM').getTime(), y: 48.63},
{x: new Date('2022-07-16 1:30 AM').getTime(), y: 58.94},
{x: new Date('2022-07-16 2:00 AM').getTime(), y: 69.19},
{x: new Date('2022-07-16 2:30 AM').getTime(), y: 69.38},
{x: new Date('2022-07-16 3:00 AM').getTime(), y: 79.54},
{x: new Date('2022-07-16 3:30 AM').getTime(), y: 89.75},
{x: new Date('2022-07-16 4:00 AM').getTime(), y: 99.73},
{x: new Date('2022-07-16 4:30 AM').getTime(), y: 100},
{x: new Date('2022-07-16 5:00 AM').getTime(), y: 98.23},
{x: new Date('2022-07-16 5:30 AM').getTime(), y: 97.79},
{x: new Date('2022-07-16 6:00 AM').getTime(), y: 83.85},
{x: new Date('2022-07-16 6:30 AM').getTime(), y: 68.15},
{x: new Date('2022-07-16 7:00 AM').getTime(), y: 28.54},
{x: new Date('2022-07-16 7:30 AM').getTime(), y: 0},
{x: new Date('2022-07-16 8:00 AM').getTime(), y: 7.25},
{x: new Date('2022-07-16 8:30 AM').getTime(), y: 15.32},
{x: new Date('2022-07-16 9:00 AM').getTime(), y: 20.35},
{x: new Date('2022-07-16 9:30 AM').getTime(), y: 20.42},
{x: new Date('2022-07-16 10:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-16 10:30 AM').getTime(), y: 20.44},
{x: new Date('2022-07-16 11:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-16 11:30 AM').getTime(), y: 29.92},
{x: new Date('2022-07-16 12:00 PM').getTime(), y: 39.04},
{x: new Date('2022-07-16 12:30 PM').getTime(), y: 38.15},
{x: new Date('2022-07-16 1:00 PM').getTime(), y: 20.44},
{x: new Date('2022-07-16 1:30 PM').getTime(), y: 20.44},
{x: new Date('2022-07-16 2:00 PM').getTime(), y: 29.92},
{x: new Date('2022-07-16 2:30 PM').getTime(), y: 39.04},
{x: new Date('2022-07-16 3:00 PM').getTime(), y: 38.15},
{x: new Date('2022-07-16 3:30 PM').getTime(), y: 43.21},
{x: new Date('2022-07-16 4:00 PM').getTime(), y: 48.63},
{x: new Date('2022-07-16 4:30 PM').getTime(), y: 58.94},
{x: new Date('2022-07-16 5:00 PM').getTime(), y: 69.19},
{x: new Date('2022-07-16 5:30 PM').getTime(), y: 69.38},
{x: new Date('2022-07-16 6:00 PM').getTime(), y: 79.54},
{x: new Date('2022-07-16 6:30 PM').getTime(), y: 89.75},
{x: new Date('2022-07-16 7:00 PM').getTime(), y: 99.73},
{x: new Date('2022-07-16 7:30 PM').getTime(), y: 100},
{x: new Date('2022-07-16 8:00 PM').getTime(), y: 98.23},
{x: new Date('2022-07-16 8:30 PM').getTime(), y: 97.79},
{x: new Date('2022-07-16 9:00 PM').getTime(), y: 83.85},
{x: new Date('2022-07-16 9:30 PM').getTime(), y: 68.15},
{x: new Date('2022-07-16 10:00 PM').getTime(), y: 28.54},
{x: new Date('2022-07-16 10:30 PM').getTime(), y: 0},
{x: new Date('2022-07-16 11:00 PM').getTime(), y: 7.25},
{x: new Date('2022-07-16 11:30 PM').getTime(), y: 15.32},
{x: new Date('2022-07-17 12:00 AM').getTime(), y: 20.35},
{x: new Date('2022-07-17 12:30 AM').getTime(), y: 20.42},
{x: new Date('2022-07-17 1:00 AM').getTime(), y: 20.44},
{x: new Date('2022-07-17 1:30 AM').getTime(), y: 20.44}
]
}
],
fill: {
type: "gradient",
gradient: {
type: "vertical",
opacityFrom: 1,
opacityTo: 1,
colorStops: [
{
offset: 20,
color: "yellow",
opacity: 1
},
{
offset: 20,
color: "green",
opacity: 1
},
{
offset: 40,
color: "green",
opacity: 1
},
{
offset: 40,
color: "blue",
opacity: 1
},
{
offset: 60,
color: "blue",
opacity: 1
},
{
offset: 60,
color: "green",
opacity: 1
},
{
offset: 80,
color: "green",
opacity: 1
},
{
offset: 80,
color: "yellow",
opacity: 1
}
]
}
},
grid: {
borderColor: '#6D6D6D'
},
xaxis: {
type: 'datetime',
forceNiceScale: true,
max: new Date('2022-07-18 12:00 AM').getTime(),
min: new Date('2022-07-15 12:00 AM').getTime(),
tooltip: {
enabled: true
},
yaxis: {
max: 150,
min: -20
}
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
Default YAxis and NULL datapoints -- correct
Modified YAxis and NO NULL datapoints -- correct
Modified YAxis and NULL datapoints -- incorrect

Related

in Rust macroquad engine, how to make sure one moving direction is selected

im coding a snake game in rust to learn the macroquad engine, im still a rust beginner and really interested in the language
the problem is i dont seem to be able to make the snake go in a single direction, like if the head is going up, dont go down at the same time
here is the update method used on the head of the snake
pub fn update(&mut self, dt: f32) {
let v_mv = match (is_key_down(KeyCode::Down), is_key_down(KeyCode::Up)) {
(true, false) => 1f32,
(false, true) => -1f32,
_ => 0f32,
};
let h_mv = match (is_key_down(KeyCode::Right), is_key_down(KeyCode::Left)) {
(true, false) => 1f32,
(false, true) => -1f32,
_ => 0f32,
};
self.player.x += dt * PLAYER_SPEED * h_mv;
self.player.y += dt * PLAYER_SPEED * v_mv;
}
there is nothing preventing the snake from moving in x and y at the same time.
I would merge the two matches:
pub fn update(&mut self, dt: f32) {
let (v_mv, h_mv): (f32, f32) = match (
is_key_down(KeyCode::Down),
is_key_down(KeyCode::Up),
is_key_down(KeyCode::Right),
is_key_down(KeyCode::Left),
) {
(true, false, false, false) => (1.0, 0.0),
(false, true, false, false) => (-1.0, 0.0),
(false, false, true, false) => (0.0, 1.0),
(false, false, false, true) => (0.0, -1.0),
_ => (0.0, 0.0),
};
self.player.x += dt * PLAYER_SPEED * h_mv;
self.player.y += dt * PLAYER_SPEED * v_mv;
}

How to circumvent `take_while` skipping values?

In trying to chain std::iter::Iterator::take_while calls together I'm losing the last values of each call.
Is there a way to chain calls together like this without skipping values?
Code Playground link:
use std::fmt;
#[derive(Clone)]
struct Point {
value: u8,
xe: u8,
xs: u8,
y: u8,
}
impl fmt::Debug for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
fn main() {
// All values following 5s within its x distance, partitioned by whether it is above or below.
// Sorted by xs (x start) (xe = x end)
#[rustfmt::skip]
let vec:Vec<Point> = vec![
Point { value: 4, xe: 1, xs: 1, y: 2 }, // 4
Point { value: 3, xe: 3, xs: 2, y: 3 }, // 3
Point { value: 5, xe: 7, xs: 4, y: 6 }, // ---- 5 -----
Point { value: 3, xe: 5, xs: 5, y: 4 }, // 3
Point { value: 6, xe: 6, xs: 6, y: 8 }, // 6
Point { value: 2, xe: 8, xs: 8, y: 3 }, // 2
Point { value: 8, xe: 10, xs: 9, y: 2 }, // 8
Point { value: 5, xe: 15, xs: 10, y: 7 }, // ---- 5 -----
Point { value: 2, xe: 12, xs: 11, y: 10 }, // 2
Point { value: 7, xe: 13, xs: 13, y: 9 }, // 7
Point { value: 4, xe: 14, xs: 14, y: 2 } // 4
];
let mut iter = vec.iter();
loop {
let c: Vec<_> = iter
.by_ref()
.take_while(|x| x.value != 5)
.cloned()
.collect();
println!("c: {:.?}", c);
if let Some(var) = iter.next() {
println!("var: {:.?}", var);
let (a, b): (Vec<_>, Vec<_>) = iter
.by_ref()
.take_while(|x| x.xe < var.xe)
.partition(|x| x.y > var.y);
println!("a: {:.?}", a);
println!("b: {:.?}", b);
} else {
break;
}
}
}
Output:
c: [4, 3]
var: 3
a: []
b: []
c: [2, 8]
var: 2
a: []
b: []
c: [4]
It should output:
c: [4, 3]
var: 5
a: [3]
b: [6]
c: [2, 8]
var: 5
a: [2, 7]
b: [4]
Using take_while with std::iter::Iterator::partition seemed a good way to make the code for this relatively clean.
In context the c, a and b values would be passed to functions whose results would be appended to a return value.
Using next_if() and from_fn():
use std::iter::from_fn;
// ...
let mut iter = vec.iter().peekable();
// ...
let c: Vec<_> = from_fn(|| iter.next_if(|x| x.value != 5))
.cloned()
.collect();
// ...
let (a, b): (Vec<_>, Vec<_>) = from_fn(|| iter.next_if(|x| x.xe < var.xe))
.partition(|x| x.y > var.y);
Using peeking_take_while() (better) or take_while_ref() from itertools, just replace the function.

How can I manually create meshes in bevy with vertices?

What do I have to do to to create a mesh for bevy with the following vertices:
let mut vertices : Vec<[f32; 3]> = Vec::new();
vertices.push([0.0, 0.0, 0.0]);
vertices.push([1.0, 2.0, 1.0]);
vertices.push([2.0, 0.0, 0.0]);
I then want to spawn a MeshBundle like so
commands
.spawn(MeshBundle {
mesh: mesh,
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
..Default::default()
});
This answer has been updated for the latest bevy = "0.9.1" and uses the default shaders.
The code below demonstrates how to:
Define vertex positions for a bevy::render::pipeline::PrimitiveTopology::TriangleList
Assign vertex normals and uv coordinates to the vertices
Create a triangle using the 3 vertices we defined
It is based on the built in shapes in bevy, which can be found here.
use bevy::prelude::*;
use bevy::render::mesh::{self, PrimitiveTopology};
fn main() {
App::new()
.insert_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
// Positions of the vertices
// See https://bevy-cheatbook.github.io/features/coords.html
mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
vec![[0., 0., 0.], [1., 2., 1.], [2., 0., 0.]],
);
// In this example, normals and UVs don't matter,
// so we just use the same value for all of them
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0., 1., 0.]; 3]);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0., 0.]; 3]);
// A triangle using vertices 0, 2, and 1.
// Note: order matters. [0, 1, 2] will be flipped upside down, and you won't see it from behind!
mesh.set_indices(Some(mesh::Indices::U32(vec![0, 2, 1])));
commands.spawn(PbrBundle {
mesh: meshes.add(mesh),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default()
});
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
You will have to define your own positions, uvs and normals according to your use case. Some shaders won't need all of these mesh attributes.
#frankenapps answer updated for bevy = 0.7
use bevy::prelude::*;
use bevy::render::mesh::{self, PrimitiveTopology};
fn main() {
App::new()
.insert_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}
/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let vertices = [
([0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0]),
([1.0, 2.0, 1.0], [0.0, 1.0, 0.0], [1.0, 1.0]),
([2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0]),
];
let indices = mesh::Indices::U32(vec![0, 2, 1, 0, 3, 2]);
let mut positions = Vec::new();
let mut normals = Vec::new();
let mut uvs = Vec::new();
for (position, normal, uv) in vertices.iter() {
positions.push(*position);
normals.push(*normal);
uvs.push(*uv);
}
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices));
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
// add entities to the world
// plane
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(mesh),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default()
});
// light
commands.spawn_bundle(PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn_bundle(PerspectiveCameraBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0)
.looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}

Piston create a a block of multiple square

i want to create something like a square of square like a a square composed of 4 small squares (4x4) for a Tetris I know how to create a simple square and move it,
but I don't know how to create a more complex figure like a 4x4 square or an L and move it like a simple square do you have any idea ?
here the code if you need it =>
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
use glutin_window::GlutinWindow;
use graphics::rectangle;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventSettings, Events};
use piston::input::{
Button, Key, PressEvent, ReleaseEvent, RenderArgs, RenderEvent, UpdateArgs, UpdateEvent,
};
use piston::window::WindowSettings;
use piston_window::Transformed;
use std::process;
struct Game {
gl: GlGraphics,
pos_x: f64,
pos_y: f64,
}
impl Game {
fn render(&mut self, arg: &RenderArgs) {
use graphics;
let BACKGROUND: [f32; 4] = [0.349019608, 0.349019608, 0.290196078, 1.0];
let COO: [f32; 4] = [0.364705882, 0.717647059, 0.870588235, 0.8];
let square_c = rectangle::square(100.0, 100.0, 30.0);
let pos_x = self.pos_x as f64;
let pos_y = self.pos_y as f64;
println!("pos x = {}", pos_x);
println!("pos y = {}", pos_y);
self.gl.draw(arg.viewport(), |c, gl| {
graphics::clear(BACKGROUND, gl);
rectangle(COO, square_c, c.transform.trans(pos_x, pos_y), gl); // deplace le carre de -200 vers la gauche
});
}
fn press(&mut self, args: &Button) {
if let &Button::Keyboard(key) = args {
match key {
Key::Up => self.pos_y -= 10.0,
Key::Down => self.pos_y += 10.0,
Key::Left => self.pos_x -= 10.0,
Key::Right => self.pos_x += 10.0,
_ => {
println!("other1");
}
}
}
}
fn release(&mut self, args: &Button) {
if let &Button::Keyboard(key) = args {
match key {
Key::Up => {
println!("Up release");
}
Key::Down => {
println!("Down release");
}
Key::Left => {
println!("Left release");
}
Key::Right => {
println!("Right release");
}
_ => {
println!("other release");
}
}
}
}
}
fn main() {
let opengl = OpenGL::V3_2;
let mut window: GlutinWindow = WindowSettings::new("Tetris Game", [400, 800])
.graphics_api(opengl)
.exit_on_esc(true)
.build()
.unwrap();
let mut game = Game {
gl: GlGraphics::new(opengl),
pos_x: 200.0,
pos_y: 0.0,
};
let mut events = Events::new(EventSettings::new());
while let Some(e) = events.next(&mut window) {
if let Some(r) = e.render_args() {
game.render(&r);
}
if let Some(b) = e.press_args() {
game.press(&b);
}
if let Some(b) = e.release_args() {
game.release(&b);
}
}
}
If you want to create a square of 4 squares, then you just have to repeat what you already have, i.e. call rectangle 4 times and position the rectangles accordingly.
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const BLUE: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
const YELLOW: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
let (x, y) = (50.0, 50.0);
rectangle(RED, rectangle::square( 0.0, 0.0, 30.0), c.transform.trans(x, y), gl);
rectangle(GREEN, rectangle::square(30.0, 0.0, 30.0), c.transform.trans(x, y), gl);
rectangle(BLUE, rectangle::square( 0.0, 30.0, 30.0), c.transform.trans(x, y), gl);
rectangle(YELLOW, rectangle::square(30.0, 30.0, 30.0), c.transform.trans(x, y), gl);
The above renders a 4 rectangles that look like this:
If you want to create an L shape, then you can just position 2 rectangles to create that shape.
rectangle(RED, [0.0, 0.0, 15.0, 30.0], c.transform.trans(x, y), gl);
rectangle(GREEN, [0.0, 30.0, 30.0, 15.0], c.transform.trans(x, y), gl);
You could also bake the positions directly into the rectangle shape, instead of using .trans(x, y), i.e. for the last one it would be [x, y + 30.0, 30.0, 15.0].
If you instead want to create a single polygon from a series of points, then you can use polygon(). The following creates the same L shape as before, just this time it's completely red.
polygon(
RED,
&[
[ 0.0, 45.0],
[ 0.0, 0.0],
[15.0, 0.0],
[15.0, 30.0],
[30.0, 30.0],
[30.0, 45.0],
],
c.transform.trans(x, y),
gl,
);
In the piston2d-graphics crate's documentation you can see additional draw functions, such as ellipse(), image() and text()

mongoDb find by matching multiple values from same index object array

I have this documents inside my db, example:
{x: 10, y: 20, val: "h"}
{x: 20, y: 70, val: "ho"}
{x: 30, y: 80, val: "hol"}
{x: 40, y: 90, val: "hola"}
{x: 50, y: 29, val: "holas"}
i want to get all the documents matching x and y values by passing an array, exampe:
[{x: 10, y 20},{x: 20, y 70}]
so to return me:
[{x: 10, y: 20, val: "h"},{x: 20, y: 70, val: "ho"}]
i have tryed in this way but doesn't work:
var ricerca = {
$in: [{x: 10, y 20},{x: 20, y 70}]
};
db.collection('exampe').find(ricerca).toArray(...
you need to use $or
$or: [{x: 10, y: 20},{x: 20, y: 70}]

Resources